(自分メモ)Selenium + Python でwait制御


ちょっとした自動化ツールでSeleniumとPythonを使ってプチツールを作成した話です。

そもそもはIE9を使っていた頃にExcelシートのデータをWebインターフェースを介して
ちょこちょこと自動反映するものだったのですが

  • IE9になってからBusy制御が逝かれた
  • もうVBAは・・・いいでしょ

ということでPythonで書き直しました。
はい、環境に入っていないものがたくさんありますので導入から。

  • firefox
  • firefoxドライバ(geckodriver)
  • selenium

で、結局Pythonでもwaitの制御で少々苦労することになるのですが
WebDriverWaitを使うことで期待の制御ができる感じです。

ただページの特徴に応じてロード完了条件を書いているので
わかっているページならいい・仕様が固定ならなのですが
もうすこし汎用的にWait制御ができないかなあ。。。というのは自分への宿題です。


# ライブラリ
from pathlib import Path
import time
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
# for headless
from selenium.webdriver.firefox.options import Options
# wait
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

# パラメータ 
DRIVER_PATH = Path('/xxxxxxxx/geckodriver')
SLEEP_TIME = 5   # 秒

# 検索パラメータ
URL = 'https://www.google.ne.jp'
SEARCH_KEYWORD = '今週の天気'

def main():
    try:
        # ブラウザ生成 firefox headlessモード
        options = Options()
        options.add_argument('-headless')
        browser = webdriver.Firefox(executable_path=str(DRIVER_PATH),
                                    firefox_options=options)
        # ブラウザロードされるまで待つ
        browser.implicitly_wait(3)

        # 試行錯誤の過程として残しておく
        ## Pageが完全ロードされるまで最大5秒待つように設定
        ## browser.set_page_load_timeout(SLEEP_TIME)
        ## browse_wait = WebDriverWait(browser, 10)

        try:
            # URLアクセス
            browser.get(URL)
            # 画面ロード完了条件を記載する
            WebDriverWait(browser, 5).until(
                EC.presence_of_all_elements_located((By.NAME, 'q'))
            )

            # 取得確認
            print(browser.title)
            # 検索設定
            elem = browser.find_element_by_name('q')
            # search boxに値が入っている可能性ありなので一旦消す
            elem.clear()
            # 検索ボックスへキーワード設定
            elem.send_keys(SEARCH_KEYWORD)
            # 検索実行
            try:
                elem.submit()
                # 画面ロード完了条件を記載する
                WebDriverWait(browser, 5).until(
                    EC.presence_of_all_elements_located((By.CLASS_NAME, 'pn'))
                )
                print(browser.title)

            except TimeoutException:
                print('loading took too much time!')

        except:
            print('get timeout!')

    finally:
        # browser を終了
        browser.quit()

if __name__ == '__main__':
    main()