【Python】Seleniumの待機処理はWebDriverWaitを使おう

本ページはプロモーションが含まれています

Seleniumを使っている時のあるある、”画面上に要素が表示されるまで”とか”入力できるようになるまで”待機する処理をまとめてみました

具体的にはWebDriverWaitとexpected_conditionsの組み合わせになるわけですがexpected_conditionsで指定できる条件が多数ありますが一通り確認してきました

WebDriverWaitについて

指定した条件を満たす(until)もしくは満たさなくなる(not_until)まで待機する便利なモジュールです

Seleniumでブラウザ操作をする上で画面遷移の完了を待つシーンは多く、単純に”sleepでxx秒待つ”処理にしてしまう長過ぎると無駄が多く、短過ぎるとエラーになりがちな雑なプログラムになってしまうのではこのWebDriverWaitは必須レベル

ただし、経験上WebDriverWaitだけではうまくいかない場合があり、最後に0.5秒ほどsleepしてあげると処理が安定する気がします

基本的なパターンはコチラ

WebDriverWait(webdriver, タイムアウトする上限秒数).until(expected_conditionsで設定する上限)

実際にサンプルソースにするとこんな感じです

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
from selenium.common.exceptions import TimeoutException, NoSuchElementException

driver = webdriver.Chrome()
driver.get('https://javeo.jp/practice_scraping/')
try:
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#hoge')))
    print('条件を満たしました')
except TimeoutException:
    print('タイムアウトしました')
except NoSuchElementException:
    print('要素が見つかりませんでした')
except Exception:
    print('予期せぬエラーが発生しました')
driver.quit()

expected_conditionsについて

WebDriverWaitとセットで使うのがこのexpected_conditions

結局のところexpected_conditionsが肝心の条件部分で、WebDriverWaitはこの条件がエラーにならなくなるまで待つだけの単純仕様

ただこのexpected_conditionsは良くも悪くも指定できる条件が多く、使いこなすには事前把握が望ましいってことでまとめてみました

expected_conditionsのオススメ関数と全関数

“オススメ”は私が個人的によく使う・使えそうだと思うものを、”分類別の全関数”ではある程度グループ分けした関数を全て目次のようにしています※クリックすすれば下部の説明箇所へ飛びます

調べて気づきましたが思ったより多くの関数があって利用シーンが謎なものもチラホラ・・

オススメの条件はできれば”Webelementで指定できる”、”指定方法で別関数を含めた使い方ができる”ことに重きを置いています

  • オススメ
  • 分類別の全関数
関数条件
visibility_of画面上に見えているか
presence_of_element_locatedDOM上に存在しているか
element_selection_state_to_be選択されている(もしくはされていない)か
element_to_be_clickable利用できる状態か
text_to_be_present_in_element_attribute指定した属性の値と一致しているか
title_containsタイトルが指定の文字と部分一致しているか
分類返値の型
DOMで判定する ※画面上に見えているかは加味しない
presence_of_element_located(locator: Tuple[str, str])WebElement
presence_of_all_elements_located(locator: Tuple[str, str])WebElement
画面上に見えているかで判定する
visibility_of(element: WebElement)WebElement
visibility_of_element_located(locator: Tuple[str, str])WebElement
visibility_of_all_elements_located(locator: Tuple[str, str])List
visibility_of_any_elements_located(locator: Tuple[str, str])List
invisibility_of_element(element: Union[WebElement, Tuple[str, str]])bool
invisibility_of_element_located(locator: Union[WebElement, Tuple[str, str]])bool
elementの状態で判定する
element_attribute_to_include(locator: Tuple[str, str], attribute_: str)bool
element_located_selection_state_to_be(locator: Tuple[str, str], is_selected: bool)bool
element_located_to_be_selected(locator: Tuple[str, str])bool
element_selection_state_to_be(element: WebElement, is_selected: bool)bool
element_to_be_clickable(mark: Union[WebElement, Tuple[str, str]])WebElement
element_to_be_selected(element: WebElement)bool
文字や要素の値で判定する
text_to_be_present_in_element(locator: Tuple[str, str], text_: str)bool
text_to_be_present_in_element_attribute(locator: Tuple[str, str], attribute_: str, text_: str)bool
text_to_be_present_in_element_value(locator: Tuple[str, str], text_: str)bool
ページタイトルで判定する
title_contains(title: str)bool
title_is(title: str)bool
ページURLで判定する
url_changes(url: str)bool
url_contains(url: str)bool
url_matches(pattern: str)bool
url_to_be(url: str)bool
ブラウザのウィンドウで判定する
number_of_windows_to_be(num_windows: int)bool
new_window_is_opened(current_handles: List[str])bool
frame要素で判定する
frame_to_be_available_and_switch_to_it(locator: Union[Tuple[str, str], str])bool
staleness_of(element: WebElement)bool
アラートポップアップで判定する
alert_is_present()Alert
複合条件にする
all_of(*expected_conditions: Callable[[D], Union[T, Literal[False]]])List
any_of(*expected_conditions: Callable[[D], T])List
none_of(*expected_conditions: Callable[[D], Any])bool

presence_of_element_located(locator: Tuple[str, str])

引数のlocatorがDOMに存在すしていれば返り値は該当したWebElementを返す(DOMなので画面上に見えるかどうかは問わない)

引数のlocatorがDOMに存在していなければ返り値はエラー(NoSuchElementException)になる

presence_of_all_elements_located(locator: Tuple[str, str])

引数のlocatorがDOMに存在すしていれば返り値は該当した全てのWebElementを返す(DOMなので画面上に見えるかどうかは問わない)

引数のlocatorがDOMに存在していなければ返り値はエラー(NoSuchElementException)になる

visibility_of(element: WebElement)

引数のelementが画面上に見えていれば返り値は該当したWebElementを返す

引数のelementが存在しなければ返り値はエラー(NoSuchElementException)になる

存在していても画面上に見えていなくても返り値はエラー(TimeoutException)になる

visibility_of_element_located(locator: Tuple[str, str])

引数のlocatorが画面上に見えていれば返り値は該当したWebElementを返す

引数のlocatorが存在しなければ返り値はエラー(NoSuchElementException)、存在していても画面上に見えていなくても返り値はエラー(TimeoutException)になる

visibility_of_all_elements_located(locator: Tuple[str, str])

引数のlocatorが全て画面上に見えていれば返り値は該当したWebElementを返す

引数のDOM上に存在しないか1つでも非表示になっていれば返り値はエラー(TimeoutException)になる

visibility_of_any_elements_located(locator: Tuple[str, str])

引数のlocatorが画面上に見えていれば返り値は該当したWebElementを返す

引数のlocatorがDOM上に存在しないか1つでも非表示になっていれば返り値はエラー(TimeoutException)になる

invisibility_of_element_located(locator: Union[WebElement, Tuple[str, str]])

引数のelementがDOM上に存在して画面上に見えていなければ返り値は該当したWebElementを返す

引数のelementがDOM上に存在していなければ返り値はTrueを返す

引数のelementがDOM上に存在して画面上に見えていれば返り値はエラー(TimeoutException)になる

※elementはWebElementとlocatorのどちらでもOK

invisibility_of_element(element: Union[WebElement, Tuple[str, str]])

実はinvisibility_of_elementのシノニム

見ての通り実はinvisibility_of_element_locatedをそのまま返してるだけ

element_attribute_to_include(locator: Tuple[str, str], attribute_: str)

引数のlocatorがDOM上に存在し、そのタグの中に引数のattribute_属性があれば返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

element_located_selection_state_to_be(locator: Tuple[str, str], is_selected: bool)

引数のlocatorがDOM上に存在し、その要素が選択されているかどうかが引数のis_selectedと一致していれば返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

※チェックボックスやラジオボタンではない場合、そもそも選択の概念がないのでis_selectedはFalseになる

element_located_to_be_selected(locator: Tuple[str, str])

引数のlocatorが選択されている状態であれば返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

element_selection_state_to_be(element: WebElement, is_selected: bool)

引数のelementがの選択状態が引数のis_selectedと一致していれば返り値はTrueを返す

引数のelementが存在しなければ返り値はエラー(NoSuchElementException)、存在していても選択状態が引数のis_selectedと一致していないと返り値はエラー(TimeoutException)になる

element_to_be_clickable(mark: Union[WebElement, Tuple[str, str]])

引数のmarkが利用できる状態になっていれば返り値は該当したWebElementを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

※markはWebElementとlocatorのどちらでもOK

element_to_be_selected(element: WebElement)

引数のelementが選択状態になっていれば返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

text_to_be_present_in_element(locator: Tuple[str, str], text_: str)

引数のtext_が引数のlocatorのtextに部分一致していると返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

text_to_be_present_in_element_value(locator: Tuple[str, str], text_: str)

引数のtext_が引数のlocatorのvalue属性に部分一致していると返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

text_to_be_present_in_element_attribute(locator: Tuple[str, str], attribute_: str, text_: str)

引数のtext_が引数のlocatorのattribute_属性に部分一致していると返り値はTrueを返す

それ以外の場合の返り値はエラー(TimeoutException)になる

つまり・・・

  • text_to_be_present_in_element=text_to_be_present_in_element_attribute(‘innerText’)
  • text_to_be_present_in_element_value=text_to_be_present_in_element_attribute(‘value’)

title_is(title: str)

ページのtitleタグが引数のtitleに完全一致していれば返り値はTrueを返す

title_contains(title: str)

ページのtitleタグが引数のtitleに部分一致していれば返り値はTrueを返す

url_contains(url: str)

ページのurlが引数のurlに部分一致していれば返り値はTrueを返す

url_matches(pattern: str)

ページのurlが引数のpatternに正規表現でマッチしていれば返り値はTrueを返す

url_to_be(url: str)

ページのurlが引数のurlに完全一致していれば返り値はTrueを返す

url_changes(url: str)

ページのurlが引数のurlに不一致であれば返り値はTrueを返す

number_of_windows_to_be(num_windows: int)

ウィンドウの数が引数のnum_windowsと一致していれば返り値はTrueを返す

new_window_is_opened(current_handles: List[str])

これは正直使い道が謎・・・

ウィンドウの数が増えたら?っぽいですがどうやって開くのか・・・

どちらにしても使い道は無いかと

frame_to_be_available_and_switch_to_it(locator: Union[Tuple[str, str], str])

引数のlocatorのframeに遷移できれば返り値はTrueを返す

staleness_of(element: WebElement)

引数のelementにアタッチできるか、らしいのですが結局is_enabled()だけ

alert_is_present()

アラートがあればそのアラートに遷移させる

any_of(*expected_conditions: Callable[[D], T])

指定したexpected_conditionsが一つでもTrueになった判定

all_of(*expected_conditions: Callable[[D], Union[T, Literal[False]]])

指定したexpected_conditionsが全てTrueになった判定

none_of(*expected_conditions: Callable[[D], Any])

指定したexpected_conditionsが全てTrueにならなかった判定

あとがき

expected_conditionsは調べてみると知らないだけで多くの関数がありました

presence_of_element_locatedやvisibility_of_element_locatedは有名ですがtext_to_be_present_in_elementやelement_to_be_clickableも有用そうで今後活用してみたい!

引数はTuple型のlocatorとWebElement型のelement、どちらでも対応できるパターンがありますがどうせなら全部どちらにも対応できるパターンにしてほしい・・・

コメント

タイトルとURLをコピーしました