2020-03-31

ウェブサイトの読み込み完了を待つ - selenium - python

ウェブサイトの要素が読み込まれる前にクリックなどの操作をするとエラーになってしまう。
そのため、特定の要素が読み込まれるまでコードを待機させる。

・待機をせずエラーを出してみる

YAHOOのトップページから検索をし、最初の結果をクリックする。
from selenium import webdriver

brows = webdriver.Chrome()

brows.get( 'https://www.yahoo.co.jp/' )
brows.maximize_window()

brows.find_element_by_xpath( '//input[@aria-label="検索したいキーワードを入力してください"]' ).send_keys( '天気 明日' )
brows.find_element_by_xpath( '//span[text()="検索"]' ).click()

brows.find_element_by_xpath('//div[@class="sw-Card__headerSpace"]').click()

#出力
# selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":"//div[@class="sw-Card__headerSpace"]"}

検索ボタンを押してすぐ次の要素を取得すると、
次のページが読み込まれていないため 「要素がない」 とエラーになる。


・要素が読み込まれるまで待機する

要素の読み込みを待つにはseleniumから3つのクラスをインポートして使う。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
※expected_conditionsは長いので EC と名前をつける。

WebDriverWait( brows, 30 ) のように一番目の引数にブラウザオブジェクト、
二番目の引数に待ち時間を指定し、
.until() で要素が指定の状態になるまで待機させる。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

WebDriverWait( brows, 30 ).until( ... )

.until()の中には ECBy を使い、要素の状態要素の探し方 を指定する。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

WebDriverWait( brows,30 ).until( EC.visibility_of_element_located( (By.XPATH, '//div[@class="sw-Card__headerSpace"]') ) )

ECの .visibility_of_element_located() は要素が 表示されている 状態。
他には
element_to_be_clickable : クリック可能な状態
element_to_be_selected : 選択された状態
presence_of_element_located : 読み込まれた状態
などがある。

( By.XPATH, '文字列' ) はXPathで要素を検索することを指定している。
他には By.IDBy.TAG_NAMEBy.CLASS_NAME など指定できる。

以上をまとめて書くと
from selenium import webdriver

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

brows = webdriver.Chrome()

brows.get( 'https://www.yahoo.co.jp/' )
brows.maximize_window()

brows.find_element_by_xpath( '//input[@aria-label="検索したいキーワードを入力してください"]' ).send_keys( '天気 明日' )
brows.find_element_by_xpath( '//span[text()="検索"]' ).click()

#ここで要素が表示されるまで最大30秒待機
WebDriverWait(brows,30).until(EC.visibility_of_element_located((By.XPATH,'//div[@class="sw-Card__headerSpace"]')))

brows.find_element_by_xpath('//div[@class="sw-Card__headerSpace"]').click()

※指定時間を超えると TimeoutException が発生しエラーとなる。


・おまけ

WebDriverWait().until() は検索した要素を返すので、
WebDriverWait().until().click() として最後の一行を省略できる。
from selenium import webdriver

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

brows = webdriver.Chrome()

brows.get( 'https://www.yahoo.co.jp/' )
brows.maximize_window()

brows.find_element_by_xpath( '//input[@aria-label="検索したいキーワードを入力してください"]' ).send_keys( '天気 明日' )
brows.find_element_by_xpath( '//span[text()="検索"]' ).click()

WebDriverWait(brows,30).until(EC.visibility_of_element_located((By.XPATH,'//div[@class="sw-Card__headerSpace"]'))).click()

0 件のコメント:

コメントを投稿