とりあえず日記

VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ→VIM→秀丸エディタ(いまここ🍄)

seleniumとpywinautoでChromeのWEBページを印刷する。


背景

我が家では嫁が家計簿を付けているので、毎月クレジットカードの利用明細を紙に印刷して提出しています。
嫁がアナログな人なので「紙で提出して!」と言って聞かないのです・・・

毎月繰り返し手作業で利用明細を印刷するのが、さすがに面倒になってきたので自動化する事に決めました。

発生した問題

このような、繰り返しのジョブ実行はjenkinsさんにおまかせするとして・・・
今回の最大の問題点はseleniumchromeブラウザの組み合わせでは、そもそも印刷ダイアログが開かないことでした。
WEBを検索すると幾つかの解決策がありますが、私の環境ではどうやっても印刷ダイアログが開きませんでした。

(WEBの情報)
以下のどれを試しても印刷ダイアログは開きませんでした。

  • driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL,'p')
  • ActionChains(driver).send_keys(Keys.CONTROL, 'p').perform()

以下は、printメソッドを実行することで印刷ダイアログが開きますが、
印刷の詳細設定を行う方法が分からず、私の実力では手詰まりになりました。

  • driver.execute_script('window.print()')
  • driver.execute_async_script('window.print()')

問題の解決方法

そこで、Windowsの操作を自動化するpywinauto(pythonモジュール)を利用して印刷ダイアログの制御を行いました。
seleniumではブラウザの制御を担当させて、pywinautoには印刷ダイアログの制御を担当させました。

(処理の流れ)
[selenium]chromeブラウザを開く。
[selenium]クレジットカードの利用明細ページへのログイン。
[selenium]利用明細ページへ移動する。
[pywinauto]印刷ダイアログを開き、印刷設定を行ってから印刷を行う。
[pywinauto]印刷ダイアログを閉じる。
[selenium]chromeブラウザを閉じる。

サンプルコード

import time,pywinauto
from selenium import webdriver

def main():
    driver = webdriver.Chrome('C:\selenium\chromedriver')
    driver.get(クレジットのログインページ)

    #ログイン処理を行う。(省略)
    
    #利用明細のページへ移動する。(省略)

    #印刷処理
    print_dialog()

    #適当に待機しないと印刷が開始されない。
    #ブラウザのテキストや画像をプリンターに送信している最中にブラウザを閉じる(driver.quit)と印刷が開始されないようだ。
    time.sleep(5)

    driver.quit()


def print_dialog():
    #
    #印刷ダイアログを開いてページ指定してから印刷する。
    #

    pywinauto.keyboard.SendKeys("+^P")

    a_check = lambda:pywinauto.findwindows.find_windows(title=u'印刷', class_name='#32770')[0]
    dialog = pywinauto.timings.WaitUntilPasses(5, 1, a_check)

    pwa_app = pywinauto.Application()
    pwa_app.connect(handle=dialog)

    window = pwa_app[u'印刷']
    window.Wait('ready')

    button = window[u'ページ指定(&G):']
    if button.is_enabled():
        #印刷範囲を指定する。
        button.Click()
        edit = window.Edit4
        edit.SetFocus()
        edit.set_text("1-2")

    #印刷ボタンを押す(Alt+P)
    pywinauto.keyboard.SendKeys("%P")
    
    #印刷ボタンを押すと印刷ダイアログは自動的に閉じるのでここでは何もしない。


if __name__ == '__main__':
    main()    

まとめ

とりあえず目的は達成しましたが、もっと良い方法があるかもしれません。
Seleniumは初めてなので今回はこれで良しとしました。

環境

  • Windows10 64bit
  • Python 3.6.3 64bit
  • Selenium 3.6.0
  • ChromeDriver 2.33.506120
  • pywinauto 0.6.1
  • chrome バージョン: 61.0.3163.100(Official Build)(64 ビット)

参考書籍

Selenium実践入門 ―― 自動化による継続的なブラウザテスト (WEB+DB PRESS plus)

Selenium実践入門 ―― 自動化による継続的なブラウザテスト (WEB+DB PRESS plus)