Selenium & Python で待機条件をカスタマイズするやり方

公開日:  

Python selenium


Ajaxなんかで動的に変化するページの場合は、ページが変更完了するまで待ちたい場合があります。
そういうときは特定の条件を満たすまで待機することができるのですが、今回はその待機条件をカスタマイズして使用する方法を書きます。

実行環境

  • Windows 10
  • Chrome 76.0.3809.87
  • ChromeDriver 76.0.3809.68
  • Python 3.6.2
  • selenium 3.141.0

定義済みの条件で待機する例

まずは元々seleniumにある待機条件を使ってみます。
以下の例ではページが読み込まれるまで待機しています。

import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('https://www.google.co.jp/imghp?hl=ja')

try:
    # 検索ボックスに入力して、サブミット
    search_box = driver.find_element_by_name('q')
    search_box.send_keys('バニラアイス')
    search_box.submit()

    # ページが読み込まれるまで待機
    wait = WebDriverWait(driver, 10)
    wait.until(EC.presence_of_all_elements_located)

    # 何かの処理
    time.sleep(3)

finally:
    driver.quit()

presence_of_all_elements_locatedを使ってページの読み込まれるのを待っています。 定義済みの条件は他にもいろいろあるのですが、それじゃ対応できないケースもあると思います。
その場合は自分で待機条件を作成することができます。

自分でカスタマイズした条件で待機する例

以下の例では、非同期に読み込まれる画像が現れるのを待っています。このとき自分で作成したクラスを待機条件として使っています。
作成するクラスはdriverを引数に持つ__call__メソッドを持っていればOKです。
__call__メソッドは条件を満たさない場合にFalseを返すようにしときます。

import time
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()
driver.get('https://www.google.co.jp/imghp?hl=ja')

try:
    # 検索ボックスに入力して、サブミット
    search_box = driver.find_element_by_name('q')
    search_box.send_keys('バニラアイス')
    search_box.submit()

    # ページが読み込まれるまで待機
    wait = WebDriverWait(driver, 10)
    wait.until(EC.presence_of_all_elements_located)

    # ページを下までスクロールする
    driver.execute_script(
        'window.scrollTo(0, document.body.scrollHeight);')
    # ここで画像が非同期に読み込まれてくるので、配置されるまで待ちたい

    # カスタム待機条件を定義
    class has_enough_images:
        def __init__(self, num):
            self.num = num
        def __call__(self, driver):
            # 画像が現れるのを待つ
            return driver.execute_script('return document.images.length;') >= self.num
    # 作った待機条件を使用
    wait.until(has_enough_images(200))

    # 何かの処理
    time.sleep(3)

finally:
    driver.quit()

こんな感じで簡単にカスタム待機条件を作成することができます。



関連記事