Selenium - ページの読み込みが完了するまで待つ(python)

Seleniumでテストをしたり、マクロを作るみると、たまに ElementNotVisibleExceptionエラーが発生します。うまく動作するコードだった仕方とき、このようなエラーを発生させ、動作しないことがあります。理由は、AjaxなどのWebページがロードされる時間差があるからです。だからページの読み込みが完了していない状態で find_element_by_idなどで存在していないアイテムを検索しようとしたら、このようなエラーが発生する可能性しかありません。

解決方法は、ページがロードされるまで待つことです。

Seleniumは以下の二つの方法のwaitを提供します。

  • Implicitly wait:決められた時間に十分待ち
  • Explicitly wait:どのような条件が満足するまで待ち

Implicitly wait

Implicitly waitを10秒に設定すると、ページがロードされ、10秒待ちます。もしページの読み込みが2秒で完了した場合より待たずに次のコードを実行します。デフォルトの設定は0秒されており、一度だけ設定すればdriverを使用するすべてのコードに適用されます。

次のコードのようにgetを呼び出す前に、wait時間を10秒に設定すると、getこのページの両方がロードされるまで待ってから、 find_element_by_idにelementを検索します。

from selenium import webdriver

driver = webdriver.Chrome("chrome path")
driver.implicitly_wait(10) # seconds
driver.get("http://somedomain/url_that_delays_loading")
myDynamicElement = driver.find_element_by_id("myDynamicElement")

Explicitly wait

Explicitly waitは、明示的にどのような条件が成立したときまで待ちます。条件が成立していなければtimeoutに設定された時間だけ最大限待ちます。

次のコードは、IDがsomeidあるelementがclickableになるまで待って、そのelementを返すコードです。 get()のコードの次にwait.until()のコードを追加してください。 wait.until()は、特定の条件が満たされるまで待って、そのelementを戻します。

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("chrome path")
driver.get("http://somedomain/url_that_delays_loading")

# wait until someid is clickable
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, 'someid')))

まずWebDriverWaitオブジェクトを生成します。引数としてdriverとtimeoutが入ります。このオブジェクトは、再利用することができるため、グローバルにオブジェクトを作成し、その後に再利用するお勧めします。

条件を設定する方法は、 wait.until(조건)のように引数に待つ条件を付けることになります。

上記の例では、条件に該当するのは、次のコードですが。 IDがsomeidあるelementがclickableになるまで待つことを意味しています。

EC.element_to_be_clickable((By.ID, 'someid')

次のコードのようにByを変更して、class nameやnameでelementを探すこともできます。

EC.element_to_be_clickable((By.CLASS_NAME, 'some_classname')
EC.element_to_be_clickable((By.NAME, 'some_name')

clickableが気に入らない場合は、以下のように element_to_be_clickableを他の条件に変更することもできます。

EC.title_is(...)
EC.title_contains(...)
EC.presence_of_element_located(...)
EC.visibility_of_element_located(...)
EC.visibility_of(...)
EC.presence_of_all_elements_located(...)
EC.text_to_be_present_in_element(...)
EC.text_to_be_present_in_element_value(...)
EC.frame_to_be_available_and_switch_to_it(...)
EC.invisibility_of_element_located(...)
EC.element_to_be_clickable(...)
EC.staleness_of(...)
EC.element_to_be_selected(...)
EC.element_located_to_be_selected(...)
EC.element_selection_state_to_be(...)
EC.element_located_selection_state_to_be(...)
EC.alert_is_present(...)

すべてのコードに適用されるimplicitly waitと異なり、explicitly waitは、コードを入れた場所にだけ待ちます。

参考

codechachaCopyright ©2019 codechacha