【Python】Seleniumでの待機処理(暗黙的な待機、明示的な待機)

時計 2021.02.27 / 時計

【Python】Seleniumでの待機処理(暗黙的な待機、明示的な待機)

本記事ではPythonのSeleniumを使ったブラウザ自動操作での、待機処理の方法について解説していきます。

待機処理はSeleniumでスクレイピングやブラウザの自動操作などで主に使う技術です。
特にAjaxなどを使った動的なWebサイトを扱う場合は必須の技術になります。

待機処理には「明示的な待機」と「暗黙的な待機」の2種類が存在します。

それぞれで使う場面や、方法が大きく異なります。
ぜひ本記事を通して、待機処理について詳しく学んでください。

Seleniumの基本的な使い方については以下記事をご参照ください。

本記事を通して以下の知識を学べます。

学べる知識
  • 明示的な待機の方法(WebDriverWait)
  • 暗黙的な待機(implicitly_wait)

明示的な待機

明示的な待機とは、定義された特定の条件が満たされるまで待機することです。

ここでの「定義された特定の条件」とは、WebDriverのDOM要素が対象となります。
つまりDOM要素が、ある状態(条件)になるまで待機するということです。

明示的な待機には次に示す2つの方法があります。

  • WebDriverWaitとexpected_conditionsの組み合わせ
  • time.sleep()

これらの手法について以下で解説していきます。

WebDriverWaitとexpected_conditionsの組み合わせ

私はSeleniumで待機処理を行う場合は、基本的にWebDriverWaitとexpected_conditionsを組み合わせた方法を使用します。

WebDriverWaitでは、タイムアウトするまでの時間を指定します。
expected_conditionsでは、明示的な待機における「特定の条件」を定義します。

これらをプログラム内で使用するために、プログラムの先頭で次のようにインポートします。

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

expected_conditionsは簡潔に記載できるようにECとしています。

後ほど詳しく解説しますが、「特定の条件」のトリガーとなるDOM要素は(By.CSS_SELECTOR, '#username')のようにタプル(ロケータ)で指定します。

タプル(ロケータ)の第一要素は、By.CSS_SELECTORやBy.IDのようByオブジェクトを使って指定するため、from selenium.webdriver.common.by import Byもプログラム先頭でインポートしてください。

WebDriverWait().until()

WebDriverWait().until()を使って、指定した要素が表示されるまで待機する処理を以下に記します。タイムアウト時間は10秒とします。

WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector)))

このWebDriverWait().until()によって、WebElementオブジェクトが返されます。
このWebElementオブジェクトに対して、click()メソッドやsend_key()メソッドなどが使用できます。

WebDriverWaitは、デフォルトでは500ミリ秒ごとにexpected_conditionsの条件が満たされているかを確認します。
タイムアウト時間を過ぎても条件が満たされないとTimeoutExceptionの例外処理が発生します。

タイムアウト時間をまとめる

WebDriverWaitの待機処理によるタイムアウト時間をすべて統一するなら、以下のように記述しておくと、プログラムを書くのが楽になります。

wait = WebDriverWait(driver, 10)

このようにすることで、待機処理を記述する際は次のように簡潔に書くことができます。

wait. until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector)))

expected_conditionsのメソッド

明示的な待機における「特定の条件」expected_conditions(EC)のメソッド一覧を以下に記します。

メソッド 条件
visibility_of_element_located 指定した要素の表示される
text_to_be_present_in_element 指定したテキストが表示される
presence_of_all_elements_located ページ内のすべての要素が読み込まれる
presence_of_element_located DOM要素内に指定した要素が現れる
alert_is_present Alertが表示される
element_to_be_clickable 要素がクリック出来る状態になる

上記のメソッドでは単数のWebElementオブジェクトが返されます。
DOM上で指定したセレクタを含む複数の要素を取得したい場合は次のようなメソッドを使用します。

visibility_of_all_elements_located ((By.CSS_SELECTOR, selector))

上記では複数のWebElementオブジェクトをリストで返します。

サンプルプログラム

明示的な待機を使用した本サイトを対象にしたブラウザ操作プログラムを下記に記します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome(executable_path='chromedriver.exe')

url = "https://office54.net"
driver.get(url)

wait = WebDriverWait(driver, 10)

selector = 'header ul.category-name li.category-python a'
element = wait. until(EC.visibility_of_element_located((By.CSS_SELECTOR, selector)))

element.click()

time.sleep()

timeクラスのsleep()メソッドでは明示した秒数、待機処理をします。

time.sleep(3)

この方法はあまり効率が良いとは言えません。
なぜなら、Webページをロードする時間はネットのスピードやサーバーの負荷状態など様々な要因で変化するからです。

しかしWebサーバーに負荷をかけすぎないように、あえてtime.sleep()を使用する場面はあるので、一概に使えないというわけではありません。

暗黙的な待機

implicitly_wait()メソッドを使用すると、find_element_by_*メソッドを使用した際に、要素が見つかるまでの待機時間を指定できます。

driver.implicitly_wait(5)

このimplicitly_wait()メソッドを使うことが暗黙的な待機を設定するということになります。

implicitly_wait()で指定できる暗黙的な待機時間のデフォルトは0です。

まとめ

本記事「Seleniumでの待機処理(暗黙的な待機、明示的な待機)」はいかがでしたか。

待機処理は、Ajaxなどを使っているWebページをSeleniumで扱う場合、特に活躍する技術です。

Seleniumでスクレイピングやブラウザの自動化を考えている方は、ぜひ本記事の内容を参考にしてください。