Selenium WebDriverWait の使い方と条件一覧

Seleniumでブラウザを自動操作していると、「要素がまだ読み込まれていなくてエラーになる」という場面によく出会います

そんなとき time.sleep() で適当に待つ人も多いですが、これだと待ちすぎたり待ち足りなかったりで安定しないんですよね

結論から言うと、Seleniumの待機は time.sleep ではなく WebDriverWait と expected_conditions の組み合わせが確実です

「条件が満たされたら、その瞬間に次へ進む」という待ち方ができるので、無駄もなければ取りこぼしもないんです

この記事では WebDriverWait の基本の書き方から、条件を指定する expected_conditions の一覧、さらに各条件がSeleniumの内部でどう動いているかまで、じっくり解説していきます

後半は全条件のリファレンスになっているので、「あの条件どう書くんだっけ」というときの辞書としても使ってくださいね

目次

WebDriverWait について

WebDriverWait は、指定した条件を満たすまで待機してくれる便利なモジュールです

Seleniumでブラウザを操作するとき、特定の条件が整うまで待ちたいシーンってすごく多いんですよね

そこで time.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('条件を満たせませんでした')
driver.quit()

import の書き方は expected_conditionsEC という別名で読み込むのが定番です、Selenium 4 でもこの書き方で問題なく動きます

Pythonでは WebDriverWait と expected_conditions は今も標準・現役で、基本パターンはずっと変わっていません、安心して使えますよ

なぜ time.sleep より良いのか

そもそも time.sleep() は「指定した秒数、問答無用で止まる」だけの処理です

import time
time.sleep(5)  # 5秒待つ

ネットワークが遅い日は5秒でも足りず、速い日は0.5秒で表示されているのに5秒待つ、みたいな無駄が出るんですね

一方の WebDriverWait は、条件が満たされた瞬間に次へ進むので、無駄な待ち時間がありません

とはいえ time.sleep も、デバッグ中にちょっと動きを止めて確認したいときなんかには便利なので、完全に使わないわけではないです

「本番の待機には WebDriverWait、確認用にたまに sleep」くらいの距離感がちょうどいいと思います

timeout と poll_frequency

WebDriverWait には、タイムアウトまでの秒数のほかに、チェックの間隔も指定できます

wait = WebDriverWait(driver, timeout=10, poll_frequency=0.5)
  • driver: WebDriverのインスタンス
  • timeout: 最大待機秒数
  • poll_frequency: チェックする間隔(秒)、省略すると0.5秒

つまり「10秒間、0.5秒ごとに条件をチェックする」という設定です

timeout には 10 のような整数秒を渡すのが基本で、Pythonではこの数値指定で問題なく動きます、まずは整数秒で覚えてしまって大丈夫です

ちなみにSelenium 4 以降は、待機時間を datetime.timedelta のような「期間オブジェクト」で扱う流れがあります(Java版などはすでに Duration 指定が中心です)

Python版は今のところ整数秒でも普通に使えるので、ここは「将来的にはそういう流れもある」くらいの認識で十分だと思います

expected_conditions について

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

結局のところ expected_conditions が肝心の条件部分で、WebDriverWait はその条件が正常終了 or True になるまで待つだけ、という仕様なんですね

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

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

また、expected_conditions の返り値はいろいろありますが、WebDriverWait とセットで使うと、WebDriverWait の仕様上、返り値は正常終了時の値 or エラー(TimeoutException)になります、try-except するときは注意してくださいね

よく使う関数

まずは私が個人的によく使う・使えそうだと思う関数だけをまとめた表です、関数名をクリックすると下のリファレンスに飛べます

関数条件
presence_of_element_locatedDOM上に存在しているか
visibility_of_element_located画面上に表示されているか
invisibility_of_element_located画面上で非表示になっているか
element_to_be_clickable画面上に表示されてかつ利用できる状態か

正直、最初はこの4つだけで大半のケースは何とかなります

分類別の全関数一覧

続いて、ある程度グループ分けした全関数を、目次のように並べた表です

スクロールできます
分類関数返値の型
DOMで判定する
(画面上に見えているかは加味しない)
presence_of_element_locatedWebElement
presence_of_all_elements_locatedList
画面上の表示・非表示で判定するvisibility_ofWebElement
visibility_of_element_locatedWebElement
visibility_of_all_elements_locatedList
visibility_of_any_elements_locatedList
invisibility_of_elementbool
invisibility_of_element_locatedbool
elementの状態で判定するelement_attribute_to_includebool
element_located_selection_state_to_bebool
element_located_to_be_selectedbool
element_selection_state_to_bebool
element_to_be_clickableWebElement
element_to_be_selectedbool
文字や要素の値で判定するtext_to_be_present_in_elementbool
text_to_be_present_in_element_attributebool
text_to_be_present_in_element_valuebool
ページタイトルで判定するtitle_containsbool
title_isbool
ページURLで判定するurl_changesbool
url_containsbool
url_matchesbool
url_to_bebool
ブラウザのウィンドウで判定するnumber_of_windows_to_bebool
new_window_is_openedbool
frame要素・状態で判定するframe_to_be_available_and_switch_to_itbool
staleness_ofbool
アラートポップアップで判定するalert_is_presentAlert
複合条件にするall_ofList
any_ofList
none_ofbool

では、ここから各関数を1つずつ詳しく見ていきます、内部のソースコードも引用しているので、挙動が気になる人はそちらもどうぞ

presence_of_element_located(locator: Tuple[str, str])

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

内部的には find_element で locator の有無を確認しているだけです

def presence_of_element_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], WebElement]:
    def _predicate(driver: WebDriverOrWebElement):
        return driver.find_element(*locator)

    return _predicate

presence_of_all_elements_located(locator: Tuple[str, str])

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

待機するだけなら presence_of_element_located と同じですね

def presence_of_all_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]:
    def _predicate(driver: WebDriverOrWebElement):
        return driver.find_elements(*locator)

    return _predicate

visibility_of_element_located(locator: Tuple[str, str])

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

実態は locator の有無確認と is_displayed() をしているだけです

def visibility_of_element_located(
    locator: tuple[str, str],
) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            return _element_if_visible(driver.find_element(*locator))
        except StaleElementReferenceException:
            return False

    return _predicate
def _element_if_visible(element: WebElement, visibility: bool = True) -> Union[Literal[False], WebElement]:
    return element if element.is_displayed() == visibility else False

visibility_of(element: WebElement)

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

引数にした WebElement がそのまま返り値になるので、単純な待機処理としてしか使うことはなさそうですね

def visibility_of(element: WebElement) -> Callable[[Any], Union[Literal[False], WebElement]]:
    def _predicate(_):
        return _element_if_visible(element)

    return _predicate

visibility_of_all_elements_located(locator: Tuple[str, str])

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

ただし、locator が1つでも DOM 上に存在しないか非表示(hidden)になっていればエラーになる絶妙仕様なので、使うことはあまりなさそうです

def visibility_of_all_elements_located(
    locator: tuple[str, str],
) -> Callable[[WebDriverOrWebElement], Union[list[WebElement], Literal[False]]]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            elements = driver.find_elements(*locator)
            for element in elements:
                if _element_if_visible(element, visibility=False):
                    return False
            return elements
        except StaleElementReferenceException:
            return False

    return _predicate

visibility_of_any_elements_located(locator: Tuple[str, str])

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

こちらは locator が DOM 上に存在しない場合のみエラーになり、1つでも表示されていれば、表示されている WebElement を返してくれます

def visibility_of_any_elements_located(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], list[WebElement]]:
    def _predicate(driver: WebDriverOrWebElement):
        return [element for element in driver.find_elements(*locator) if _element_if_visible(element)]

    return _predicate

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

visibility_of_element_located の逆で、DOM 上に見えてないことを検知してくれます

DOM 上になければ True、DOM 上にあるけど非表示なら対象の WebElement を返してくれます、ローディング画面が消えるのを待つ、みたいなときに便利ですね

def invisibility_of_element_located(
    locator: Union[WebElement, tuple[str, str]],
) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            target = locator
            if not isinstance(target, WebElement):
                target = driver.find_element(*target)
            return _element_if_visible(target, visibility=False)
        except (NoSuchElementException, StaleElementReferenceException):
            # In the case of NoSuchElement, returns true because the element is
            # not present in DOM. The try block checks if the element is present
            # but is invisible.
            # In the case of StaleElementReference, returns true because stale
            # element reference implies that element is no longer visible.
            return True

    return _predicate

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

実は invisibility_of_element_located のシノニム(別名)です

見ての通り、実は locator でも受け付けできて、invisibility_of_element_located をそのまま返しているだけなんですね

def invisibility_of_element(
    element: Union[WebElement, tuple[str, str]],
) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]:
    return invisibility_of_element_located(element)

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

引数の locator が DOM 上に存在し、さらにそのタグの中に引数の attribute_ 属性があるかで照合します(それ以外はエラー)

使い道としては、JavaScriptで要素が追加されるときぐらいですかね

def element_attribute_to_include(locator: tuple[str, str], attribute_: str) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            element_attribute = driver.find_element(*locator).get_attribute(attribute_)
            return element_attribute is not None
        except StaleElementReferenceException:
            return False

    return _predicate

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

引数の locator が DOM 上に存在し、さらにその要素の選択状況と引数の is_selected が合っているかで判定を返してくれます

locator が DOM 上に存在しないときはエラーになります

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

def element_located_selection_state_to_be(
    locator: tuple[str, str], is_selected: bool
) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            element = driver.find_element(*locator)
            return element.is_selected() == is_selected
        except StaleElementReferenceException:
            return False

    return _predicate

element_located_to_be_selected(locator: Tuple[str, str])

引数の locator が選択されている状態であるかで照合します

is_selected() はあまり使う機会がないと思うんですよね

def element_located_to_be_selected(locator: tuple[str, str]) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        return driver.find_element(*locator).is_selected()

    return _predicate

element_to_be_selected(element: WebElement)

element_located_to_be_selected の引数が locator から WebElement になった版です

def element_to_be_selected(element: WebElement) -> Callable[[Any], bool]:
    def _predicate(_):
        return element.is_selected()

    return _predicate

element_selection_state_to_be(element: WebElement, is_selected: bool)

element_to_be_selected で is_selected() == False が選べるようになっただけです

def element_selection_state_to_be(element: WebElement, is_selected: bool) -> Callable[[Any], bool]:
    def _predicate(_):
        return element.is_selected() == is_selected

    return _predicate

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

まず引数が mark(WebElement と locator のどちらでもOK)になっているのに好感が持てます
※全部そうしてほしい

内部的には visibility_of かつ is_enabled() なので、clickable という名前からチェックボックス向けのような印象を受けますが、input タグなどにも有効です(むしろこっちの方が利用頻度が高い)

def element_to_be_clickable(
    mark: Union[WebElement, tuple[str, str]],
) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]:
    # renamed argument to 'mark', to indicate that both locator
    # and WebElement args are valid
    def _predicate(driver: WebDriverOrWebElement):
        target = mark
        if not isinstance(target, WebElement):  # if given locator instead of WebElement
            target = driver.find_element(*target)  # grab element at locator
        element = visibility_of(target)(driver)
        if element and element.is_enabled():
            return element
        return False

    return _predicate

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

XPATHの [text()=’hoge’] を事前チェックできる感じです

需要がありそうでなさそう、、、で、やっぱりありそうな関数です、「処理が完了しました」のような表示を待つときに便利ですよ

def text_to_be_present_in_element(locator: tuple[str, str], text_: str) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            element_text = driver.find_element(*locator).text
            return text_ in element_text
        except StaleElementReferenceException:
            return False

    return _predicate

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

text_to_be_present_in_element を text から value 属性に変えてみました、という関数です

もともと微妙な需要だったのに、さらに下がってる気がします

def text_to_be_present_in_element_value(
    locator: tuple[str, str], text_: str
) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            element_text = driver.find_element(*locator).get_attribute("value")
            if element_text is None:
                return False
            return text_ in element_text
        except StaleElementReferenceException:
            return False

    return _predicate

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

text_to_be_present_in_element_value を、value 以外の属性を選べるようにしてみました

じゃあ text_to_be_present_in_element_value いらない・・・となりますね

def text_to_be_present_in_element_attribute(
    locator: tuple[str, str], attribute_: str, text_: str
) -> Callable[[WebDriverOrWebElement], bool]:
    def _predicate(driver: WebDriverOrWebElement):
        try:
            element_text = driver.find_element(*locator).get_attribute(attribute_)
            if element_text is None:
                return False
            return text_ in element_text
        except StaleElementReferenceException:
            return False

    return _predicate

title_is(title: str)

title との完全一致判定です

title 自体ちょっと使いにくいのに、完全一致はなかなか難しい印象です

def title_is(title: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return driver.title == title

    return _predicate

title_contains(title: str)

こちらは title の部分一致判定です

完全一致よりは現実的だけど、やっぱり title で照合はしないと思います

def title_contains(title: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return title in driver.title

    return _predicate

url_contains(url: str)

url の部分一致で判定します

個人的には待機処理の条件に url はあまり使わないかなと思います、ただ、ボタンを押してページが切り替わるのを待ちたいときには出番がありますね

def url_contains(url: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return url in driver.current_url

    return _predicate

url_matches(pattern: str)

こちらは url を正規表現で判定します

URLにIDなどが含まれていて完全一致では指定しづらいとき、正規表現で柔軟に待てるのは便利ですね、ちなみに Selenium 4 で整理された比較的新しい条件です

def url_matches(pattern: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return re.search(pattern, driver.current_url) is not None

    return _predicate

url_to_be(url: str)

url の完全一致で判定します

遷移先のURLがきっちり決まっているときには使えますよ

def url_to_be(url: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return url == driver.current_url

    return _predicate

url_changes(url: str)

url の不一致で判定します、指定したURLから変わるまで待つ、という条件ですね

クリック後にページが切り替わるのを待つ、みたいなときに自然に使えます、こちらも Selenium 4 系で整理された条件です

def url_changes(url: str) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return url != driver.current_url

    return _predicate

number_of_windows_to_be(num_windows: int)

ウィンドウ(=タブ)の数で照合します

新しいタブが開くのを待ちたいとき以外は、出番が少なめかもしれません

def number_of_windows_to_be(num_windows: int) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return len(driver.window_handles) == num_windows

    return _predicate

new_window_is_opened(current_handles: List[str])

新しいウィンドウができるまで待ってくれる、らしいです

number_of_windows_to_be と用途は近いですが、開く前のウィンドウ数を渡しておけば、それより増えたかどうかで判定してくれます

def new_window_is_opened(current_handles: list[str]) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        return len(driver.window_handles) > len(current_handles)

    return _predicate

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

指定の frame に移動できるまで待ちます

待機処理としてより、switch_to.frame を安全にする使い方なら需要がありそうです、iframe を操作するときに役立ちますね

def frame_to_be_available_and_switch_to_it(
    locator: Union[tuple[str, str], str, WebElement],
) -> Callable[[WebDriver], bool]:
    def _predicate(driver: WebDriver):
        try:
            if isinstance(locator, Iterable) and not isinstance(locator, str):
                driver.switch_to.frame(driver.find_element(*locator))
            else:
                driver.switch_to.frame(locator)
            return True
        except NoSuchFrameException:
            return False

    return _predicate

staleness_of(element: WebElement)

なんでこんな名前になったのか、、実態は is_enabled だけです、要素が古くなる(DOMから削除される)のを検知できるので、ページ遷移の確認に便利ですね

def staleness_of(element: WebElement) -> Callable[[Any], bool]:
    def _predicate(_):
        try:
            # Calling any method forces a staleness check
            element.is_enabled()
            return False
        except StaleElementReferenceException:
            return True

    return _predicate

alert_is_present()

アラートに遷移できるかを判定します

frame_to_be_available_and_switch_to_it と同じく、待機処理としてより、switch_to.alert を安全にする使い方なら需要がありそうです

def alert_is_present() -> Callable[[WebDriver], Union[Alert, Literal[False]]]:
    def _predicate(driver: WebDriver):
        try:
            return driver.switch_to.alert
        except NoAlertPresentException:
            return False

    return _predicate

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

指定した複数の expected_conditions が、1つでも True になればOKという条件です

「成功表示か、エラー表示の、どちらかが出るまで待つ」みたいな分岐に便利です、こちらも Selenium 4 で追加されました

def any_of(*expected_conditions: Callable[[D], T]) -> Callable[[D], Union[Literal[False], T]]:
    def any_of_condition(driver: D):
        for expected_condition in expected_conditions:
            try:
                result = expected_condition(driver)
                if result:
                    return result
            except WebDriverException:
                pass
        return False

    return any_of_condition

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

こちらは指定した複数の expected_conditions が、全て True になればOKという条件です

複数の条件をまとめてチェックしたいときに使います、any_of とセットで Selenium 4 で追加されました

def all_of(
    *expected_conditions: Callable[[D], Union[T, Literal[False]]],
) -> Callable[[D], Union[list[T], Literal[False]]]:
    def all_of_condition(driver: D):
        results: list[T] = []
        for expected_condition in expected_conditions:
            try:
                result = expected_condition(driver)
                if not result:
                    return False
                results.append(result)
            except WebDriverException:
                return False
        return results

    return all_of_condition

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

こちらは指定した複数の expected_conditions が、1つも True にならなければOKという条件です

「エラー表示が出ないまま処理が進んだか」を確かめたいときなんかに使えます

def none_of(*expected_conditions: Callable[[D], Any]) -> Callable[[D], bool]:
    def none_of_condition(driver: D):
        for expected_condition in expected_conditions:
            try:
                result = expected_condition(driver)
                if result:
                    return False
            except WebDriverException:
                pass
        return True

    return none_of_condition

expected_conditions にない条件は lambda で自作できる

ここまで全関数を見てきましたが、「ちょうどいい条件がない」というケースもあります

そんなときは、until に自作の関数(条件)を渡せます

「driver を受け取って、満たされたら値を返す(満たされなければ False を返す)」関数を渡せばいいだけなので、lambda でサクッと書けるんですね

from selenium.webdriver.common.by import By

# 要素のテキストが空でなくなるまで待つ自作条件
element = WebDriverWait(driver, 10).until(
    lambda d: d.find_element(By.ID, "status") if d.find_element(By.ID, "status").text != "" else False
)

expected_conditions に用意されていない細かい条件で待ちたいときは、この lambda 方式を覚えておくと一気に応用が利きます

そもそも要素の取得自体に迷うときは、Seleniumで要素を取得する find_element の使い方もあわせて読むと、待機とセットでスッキリ書けるようになりますよ

WebDriverWait のよくあるエラーと注意点

TimeoutException が出る

指定した時間内に条件が満たされなかったときに出るエラーです

一番よく見るエラーですね

from selenium.common.exceptions import TimeoutException

try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.ID, "main"))
    )
except TimeoutException:
    print("要素が見つかりませんでした")

try-except で囲んで、タイムアウト時の処理を書いておくと安心です

原因としては、セレクタが間違っているか、本当に表示まで時間がかかっているかのどちらかが多いです

要素は見つかるのにクリックできない

presence では見つかるのに、いざクリックするとエラーになることがあります

これは要素は存在するけど、まだ表示されていない・操作できない状態だからですね

そういうときは element_to_be_clickable を使うと解決することが多いです

暗黙的な待機と混ぜると危険

ここは2026年の今でも引っかかる人が多いポイントなので、しっかり押さえておきたいところです

Seleniumには WebDriverWait(明示的な待機)とは別に、implicitly_wait() という「暗黙的な待機」もあります

driver.implicitly_wait(10)  # 要素が見つかるまで最大10秒待つ(全体に適用)

これ自体は楽な仕組みなんですが、WebDriverWait と併用すると、待機時間が予期せず長くなることがあります

これは両方の待機が重なってしまうからです

例えば暗黙的な待機を10秒、明示的な待機を15秒に設定していると、タイムアウトが20秒後に起きる、といった予測しづらい挙動になることがあります

Seleniumの公式ドキュメントでも、暗黙的な待機と明示的な待機は混在させないようにと、はっきり警告されています

個人的には WebDriverWait に統一する派です、条件ごとに細かく待てて、挙動も読みやすいので

こうした自動化スクリプトを実際に動かすときは、ログインや個人情報の扱いなど安全面の配慮も大切です、不安な方は自動化を始める前に知っておきたい安全性の基本もあわせて読んでみてくださいね

あとがき

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

presence_of_element_locatedvisibility_of_element_located は有名ですが、text_to_be_present_in_elementelement_to_be_clickable も有用そうで、今後活用してみたいと思います

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

ポイントをまとめると、こんな感じです

  • 本番の待機は time.sleep ではなく WebDriverWait を使う
  • WebDriverWait は「条件が満たされるまで待つ」賢い待機
  • 条件は expected_conditions で指定する
  • よく使うのは presence / visibility / clickable / invisibility あたり
  • 足りない条件は lambda で自作できる
  • 暗黙的な待機との併用は避ける

最初は presence_of_element_locatedelement_to_be_clickable の2つだけ覚えておけば、だいたい何とかなります

実際にPythonでスクレイピングを動かしてみたい方は、Pythonでnetkeibaをスクレイピングしてみた実例もどうぞ、待機処理が実戦でどう効いてくるかイメージしやすいと思います

あなたのSeleniumの自動化が、もっと安定して動くようになればうれしいです

クラウドソーシングPR

最後に・・・

クラウドワークスココナラでお仕事受け付けています!

PythonとExcelを中心に仕事に役立つ業務ツールや自動化、スクレイピングツールの作成を受注していて、クラウドワークスでは気が付けば100件以上のお仕事を受注してきました!

会社員をやりながらの副業なので時間の捻出は相応ですが、クライアントの方々と近い立場でこちらからも提案しながら活動していますのでお悩みあれば是非ご相談ください

ココナラのプロフィールページへ

"ココナラ"に新規登録する際は1,000Pもらえる紹介コード使ってください

78E62K

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAとPythonを中心にユーザー側でできるITを自己学習しているので備忘録半分、学習履歴を残して同じ道を辿る人の参考になればとブログを始めました

副業でスクレイピングツール作成を中心にできることを色々やっていますのでご相談いただけるとありがたいです!


クラウドワークスのページへ


ココナラのページへ

コメント

コメントする

目次