モダンなWebアプリケーションの多くは、ページ全体をリロードすることなく、JavaScriptを用いて一部のテキストのみを動的に書き換えます。
このような動的なUIをSeleniumで自動操作する場合、単に要素が表示されるのを待つだけでは不十分なケースが少なくありません。
特定のメッセージが表示されるまで、あるいはステータスが「完了」に変わるまで処理を一時停止させたいといったシナリオは、実務において非常に頻繁に発生します。
本記事では、PythonとSeleniumを用いて、要素内のテキストが特定の状態に変化するのを確実に待機する実装手法について詳しく解説します。
Seleniumにおける待機処理の重要性
Webブラウザの自動操作において、プログラムの実行速度はブラウザのレンダリング速度を大きく上回ります。
そのため、適切な待機処理を組み込まなければ、要素が見つからないことによるNoSuchElementExceptionや、操作対象が準備できていないことによるエラーに直面します。
特にテキストの変更は、HTML要素自体は既に存在しているものの「中身の文字だけが後から変わる」という挙動を示すため、要素の存在確認だけでは回避できない問題が発生します。
こうした状況を解決するために、Seleniumでは「明示的な待機(Explicit Wait)」の活用が推奨されています。
暗黙的な待機と明示的な待機の違い
Seleniumには大きく分けて2種類の待機方法が存在しますが、その性質は大きく異なります。
| 待機方法 | 特徴 | テキスト変更への対応 |
|---|---|---|
| 暗黙的な待機 (Implicit Wait) | 一度設定すると全ての要素検索に一律の待ち時間を適用する | 要素の出現には対応できるが、中身の変化は検知できない |
| 明示的な待機 (Explicit Wait) | 特定の条件(Expected Conditions)が満たされるまで個別に待機する | テキストの特定内容への変化を正確に検知可能 |
動的なテキスト変更に対応するためには、特定の条件を指定できる明示的な待機が必須となります。
テキスト変更を待機するためのExpected Conditions
Seleniumのselenium.webdriver.support.expected_conditionsモジュールには、テキストの状態を監視するための便利なメソッドが用意されています。
これらのメソッドをWebDriverWaitと組み合わせることで、ポーリング(繰り返し確認)処理を自作することなく、スマートに待機を実装できます。
text_to_be_present_in_element
text_to_be_present_in_elementは、指定した要素の中に特定の文字列が含まれるようになるまで待機するメソッドです。
これは、ローディング中の「読み込み中…」という表示が「完了しました」というテキストに変わるのを待つような場面で最適です。
完全一致ではなく、指定した文字列が含まれている(部分一致)かどうかで判定される点に注意してください。
text_to_be_present_in_element_value
一方で、inputタグやtextareaタグなど、ユーザーが入力するフィールドの値を監視したい場合にはtext_to_be_present_in_element_valueを使用します。
HTMLのタグに挟まれたテキストではなく、value属性の値が変化するのを待機する場合に有効な手法です。
JavaScriptによってフォームの値が自動補完されるサイトのテストなどで威力を発揮します。
実装コード:テキストが特定の内容に変わるまで待機する
それでは、具体的にPythonコードで実装する方法を見ていきましょう。
以下のサンプルコードでは、ボタンをクリックした後に通信が発生し、数秒後に「処理中」から「完了」に変わる要素を想定しています。
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
# Chromeを起動
driver = webdriver.Chrome()
try:
# ターゲットサイトへアクセス(例)
driver.get("https://example.com/dynamic-text")
# 処理を開始するボタンをクリック
driver.find_element(By.ID, "start-button").click()
# 最大15秒間、IDが 'status' の要素に「完了」というテキストが表示されるまで待機
wait = WebDriverWait(driver, 15)
target_element_id = "status"
# text_to_be_present_in_element( (Locator), "期待する文字列" )
wait.until(EC.text_to_be_present_in_element((By.ID, target_element_id), "完了"))
# 待機完了後に要素のテキストを取得して確認
result_text = driver.find_element(By.ID, target_element_id).text
print(f"検知したテキスト: {result_text}")
finally:
# ブラウザを閉じる
driver.quit()
検知したテキスト: 処理が正常に完了しました
このコードのポイントは、wait.untilメソッドにEC.text_to_be_present_in_elementを渡している点です。
これにより、指定した15秒のタイムアウトまでの間、Seleniumは一定間隔で要素のテキストを確認し続けます。
「完了」という文字が含まれた瞬間に待機が解除されるため、最短の時間で次の処理へ移行できるのが大きなメリットです。
応用編:より柔軟なテキスト待機の実装
標準のexpected_conditionsだけでは対応が難しい、より複雑なケースも存在します。
例えば、「テキストが空でなくなるまで待ちたい」あるいは「特定の単語が含まれない状態になるまで待ちたい」といった場合です。
このようなケースでは、Lambda(ラムダ)式を用いてカスタムの待機条件を記述するのが効率的です。
Lambda式を活用したカスタム待機
WebDriverWaitのuntilメソッドには、引数にdriverを受け取り、真偽値を返す関数を渡すことができます。
これを利用すれば、どのような複雑な条件でも待機ロジックを組み立てることが可能です。
# 要素のテキストが「0」以外になるまで待機するカスタム条件
wait = WebDriverWait(driver, 10)
wait.until(lambda d: d.find_element(By.ID, "counter").text != "0")
# 要素のテキストの長さが5文字以上になるまで待機
wait.until(lambda d: len(d.find_element(By.ID, "message").text) >= 5)
このようにLambda式を使うことで、ライブラリ側で用意されていない条件でも自由自在に制御することができます。
特に2026年現在のフロントエンド開発では、リアルタイムに数値が変動するダッシュボードのようなUIが増えているため、このテクニックは非常に重宝します。
2026年のWeb開発環境における待機の注意点
近年のReactやVue.js、Next.jsといったフレームワークを使用したサイトでは、DOMの再描画が非常に高速です。
そのため、テキストが変更される瞬間に一時的に要素がDOMから削除され、別の要素として再生成される挙動を見せることがあります。
このような場合、事前に取得していた要素のインスタンスを使い回すとStaleElementReferenceExceptionが発生します。
これを防ぐためには、EC.text_to_be_present_in_elementのように、内部で毎回要素を検索し直すロケータ(By.IDなど)を渡す方式を採用するのが最も安全です。
また、ネットワークの遅延やサーバーのレスポンス低下を考慮し、タイムアウト時間は一律に短く設定しすぎず、環境に合わせた余裕を持たせることも実戦では重要になります。
まとめ
Seleniumで動的に変化するテキストを確実にキャッチするには、WebDriverWaitとexpected_conditionsの組み合わせが最も堅実な解決策となります。
標準的なテキスト検知であればtext_to_be_present_in_elementを使い、より詳細な条件分岐が必要な場合にはLambda式を活用することで、不安定なテスト(フラッキーなテスト)を大幅に削減できます。
「time.sleep」による固定時間の待機は、実行時間の無駄やエラーの原因となるため、極力避けるべきです。
今回紹介した明示的な待機のテクニックを駆使して、堅牢でメンテナンス性の高いスクレイピング・テストコードの実装を目指しましょう。
