はじめに
ページを読み込み終わる前に、後続の処理を実行してしまい、処理が失敗してしまう事象が発生した。
環境
Python 3.12.4
Selenium 4.23.1
Windows 10 22H2
起きた問題
ページの読み込みが終わる前に、後続の処理を実行してしまい、処理が失敗してしまう事象が発生した。
サンプルコードは、ログインを自動化する処理のコードである。
サンプルコードでは、ログインID入力欄、パスワード入力欄、ログインボタンが読み込まれる前に、ログインID・パスワードを入力し、ログインボタンを押下する処理が発生する。
サンプルコード
auto_login.py
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
def main():
LOGUIN_URL = 'https://hoge.hoge/login'
USER_ID = "TestUser"
PASSWORD = "TestPassword"
with webdriver.Chrome() as driver:
driver.maximize_window()
driver.get(LOGUIN_URL)
# ログインページを読み込み終わるまで待つ。
wait = WebDriverWait(driver=driver,timeout=30)
wait.until(EC.presence_of_all_elements_located())
driver.find_element(By.ID,"user_id").send_keys(USER_ID)
driver.find_element(By.ID,"password").send_keys(PASSWORD)
driver.find_element(By.ID,"login_button").click()
main()
原因
下記を読み込み待ちに利用していたこと。
wait.until(EC.presence_of_all_elements_located())
対処方法
読み込まれる必要がある要素の分だけ、下記を実行し、読み込み待ちを行う。
wait.until(EC.presence_of_element_located((By.ID,"hoge")))
サンプルコード
auto_login_修正.py
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
def main():
LOGUIN_URL = 'https://hoge.hoge/login'
USER_ID = "TestUser"
PASSWORD = "TestPassword"
with webdriver.Chrome() as driver:
driver.maximize_window()
driver.get(LOGUIN_URL)
# ログインページを読み込み終わるまで待つ。
wait = WebDriverWait(driver=driver,timeout=30)
- wait.until(EC.presence_of_all_elements_located())
+ ELEMENT_IDS = ["user_id","password","login_button"]
+ for element_id in ELEMENT_IDS:
+ wait.until(EC.presence_of_element_located((By.ID,element_id)))
- driver.find_element(By.ID,"user_id").send_keys(USER_ID)
- driver.find_element(By.ID,"password").send_keys(PASSWORD)
- driver.find_element(By.ID,"login_button").click()
+ driver.find_element(By.ID,ELEMENT_IDS[0]).send_keys(USER_ID)
+ driver.find_element(By.ID,ELEMENT_IDS[1]).send_keys(USER_ID)
+ driver.find_element(By.ID,ELEMENT_IDS[2]).click()
main()
さいごに
本記事では、下記に示すコードで、処理に必要な要素の読み込みが終わるまで処理待ちをする方法を示した。
wait.until(EC.presence_of_element_located((By.ID,"hoge")))
備考
本記事は、「参考程度」と考えてほしい。
なぜなら、「サイトの作りによっては適切な方法が異なる」と思われるためである。
本記事で紹介した方法を、使わなくてもうまくいく場合と使ってもうまくいかない場合がある。
TIPS
ページの読み込み待ちで、time.sleep()
の利用は推奨しない。
理由は、以下の通りである。
- 指定した秒数以内で、処理に必要な要素の読み込みが終わらない場合、処理に失敗してしまう。
- 指定した秒数が長すぎると、不必要に処理時間が長くなる。
サンプルコード
LOAD_WAIT_SECONDS = 1
time.sleep(LOAD_WAIT_SECONDS)
参考文献