【Python】Seleniumで要素の表示・読み込み完了を正しく待機する

目次

概要

最近のWebサイト(SPAやAjax使用サイト)では、ページを開いた直後にはまだ要素が存在せず、少し遅れて表示されることがよくあります。

Seleniumでエラーを出さずにこれらを操作するためには、要素が出現するまで適切にプログラムを一時停止させる「待機処理」が不可欠です。ここでは「暗黙的待機」と「明示的待機」の2つの手法を解説します。

仕様(入出力)

  • 暗黙的待機 (implicitly_wait):
    • 入力: 待機する最大秒数
    • 効果: ドライバの寿命全体に設定が適用され、要素が見つからない場合に指定時間までポーリング(再確認)し続ける。
  • 明示的待機 (WebDriverWait):
    • 入力: ドライバ、最大秒数、終了条件(EC)
    • 効果: 特定の条件(要素が見えた、クリック可能になった等)が満たされるまで、その場だけで待機する。

基本の使い方

ドライバに「見つからなかったら最大○秒待ってね」と一律で指示する、最も手軽な「暗黙的待機」の設定です。

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

# 暗黙的待機を設定 (最大5秒)
# 以降、find_element実行時に要素がなければ5秒間探し続けます
driver.implicitly_wait(5)

try:
    driver.get("https://example.com")
    # すぐに見つからなくても、5秒以内に出現すれば取得できます
    element = driver.find_element(By.TAG_NAME, "h1")
    print(element.text)
finally:
    driver.quit()

コード全文

より柔軟で、実務で推奨される「明示的待機 (WebDriverWait)」を使用した実装例です。

「要素が存在するか」だけでなく、「表示されているか(可視性)」を条件に指定して待機します。

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

def wait_for_element_demo():
    """
    WebDriverWaitを使用して、特定の要素が表示されるまで待機するデモ関数。
    """
    driver = webdriver.Chrome()
    
    # 待機時間の定義(最大10秒)
    wait = WebDriverWait(driver, 10)
    
    try:
        # 遅延ロードのテストサイト等を開く想定
        driver.get("https://morinokabu.com") 

        print("要素の出現を待機しています...")

        # 明示的待機の実行
        # until(条件) : 条件がTrueになるか、Web要素を返すまで待機
        # EC.visibility_of_element_located : 要素がDOMにあり、かつサイズが0以上で表示されていること
        target_element = wait.until(
            EC.visibility_of_element_located((By.TAG_NAME, "h1"))
        )
        
        # 待機を抜けた=要素が表示された状態
        print(f"要素を取得しました: {target_element.text}")

    except TimeoutException:
        print("指定時間内に要素が表示されませんでした(タイムアウト)。")
    
    except Exception as e:
        print(f"予期せぬエラー: {e}")

    finally:
        driver.quit()

if __name__ == "__main__":
    wait_for_element_demo()

カスタムポイント

2つの待機メソッドの違い

メソッド書き方特徴・用途
implicitly_waitdriver.implicitly_wait(秒)設定型。一度書けば以降全ての find_element に適用される。「とりあえず全部待ちたい」簡単なスクリプト向け。
WebDriverWaitWebDriverWait(driver, 秒).until(...)都度実行型。特定の要素に対して「表示されたら」「クリック可能なら」など詳細な条件で待てる。安定性が高く、実務ではこちらが推奨される。

よく使う終了条件 (Expected Conditions)

from selenium.webdriver.support import expected_conditions as EC として使用します。

  • EC.presence_of_element_located((By.ID, "id"))
    • HTML内に要素が存在すればOK(表示されていなくてもOK)。
  • EC.visibility_of_element_located((By.ID, "id"))
    • 要素が存在し、かつ画面に表示されている(高さ・幅が0より大きい)。
  • EC.element_to_be_clickable((By.ID, "id"))
    • 要素が表示されており、かつクリック可能(無効化されていない)。

注意点

  1. 併用禁止
    • implicitly_waitWebDriverWait を混ぜて使用しないでください。
    • 予期せぬ長い待機時間が発生したり、動作が不安定になったりする原因になります。どちらか一方(基本は WebDriverWait)に統一しましょう。
  2. タプルの二重括弧
    • EC のメソッドに渡す引数は (By.ID, "name") という1つのタプルである必要があります。
    • EC.presence_of_element_located(By.ID, "name") ではなく、
    • EC.presence_of_element_located((By.ID, "name")) と二重括弧になる点に注意してください。
  3. タイムアウト例外
    • 指定時間内に条件が満たされない場合、TimeoutException が発生します。必ず try-except で捕捉して、適切なエラー処理(リトライやログ出力)を行ってください。

応用

「ボタンがクリックできるようになるまで待ってから、クリックする」という、最も安全な操作パターンの実装です。

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 safe_click(driver, locator, timeout=10):
    """
    要素がクリック可能になるのを待ってからクリックするヘルパー関数
    """
    try:
        element = WebDriverWait(driver, timeout).until(
            EC.element_to_be_clickable(locator)
        )
        element.click()
        print("クリック成功")
    except Exception:
        print("クリックできませんでした")

# 使用例
if __name__ == "__main__":
    driver = webdriver.Chrome()
    driver.get("https://example.com")
    
    # ID="submit-btn" のボタンを安全にクリック
    safe_click(driver, (By.ID, "submit-btn"))
    
    driver.quit()

まとめ

スクレイピングや自動テストの不安定さ(Flaky)の多くは、この「待機処理」の不備が原因です。

手軽な implicitly_wait も便利ですが、確実な動作のためには WebDriverWait と ExpectedConditions を使いこなし、「何の状態を待つのか」を明確に記述する癖をつけましょう。

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

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次