閉じる

Seleniumで要素数をカウントする際の待機処理の正解|WebDriverWaitを使った実例

Webブラウザの自動操作において、リストの項目数や検索結果の件数を正確にカウントしたい場面は非常に多く存在します。

しかし、現代のWebアプリケーションはJavaScriptを用いて動的にコンテンツを生成するため、ページ遷移直後にカウントを行うと正しい数値が得られないことが多々あります。

特に、要素が見つからない場合にエラーを投げず、空のリストを返す「find_elements」メソッドの性質が、初心者にとっての大きな壁となっています。

本記事では、Selenium(Python)を使用して要素数を正確に取得するために欠かせない、「WebDriverWait」を活用した待機処理の正解について詳しく解説します。

適切な待機ロジックを実装することで、処理の高速化とスクリプトの安定性を両立させることが可能になります。

なぜ要素数のカウントには「待機」が不可欠なのか

Seleniumで特定の要素が何個あるかを調べる際、多くの人が「len(driver.find_elements(…))」というコードを記述します。

しかし、このコードをページ読み込み直後に実行すると、本来10個あるはずの要素が0個や1個としてカウントされる現象が発生します。

これは、ブラウザがHTMLの解析を完了していても、その後のJavaScriptによる非同期通信(Ajax)での要素追加が完了していないためです。

ブラウザの表示が追いついていない状態でカウント処理だけが先行してしまうと、自動テストやスクレイピングの精度は著しく低下します。

find_elementsメソッドの仕様と注意点

Seleniumの要素取得メソッドには、単一の要素を取得する「find_element」と、複数の要素を取得する「find_elements」の2種類があります。

「find_element」は要素が見つからない場合に例外(NoSuchElementException)を発生させますが、「find_elements」は要素が1つも見つからなくても例外を出さず、空のリストを返します。

この仕様により、暗黙的な待機(Implicit Wait)を設定していても、要素が0個の状態では即座に処理が継続されてしまう場合があります。

そのため、要素数をカウントする際には、単なるリストの取得ではなく「特定の条件を満たすまで待つ」という明示的な待機が必要となります。

推奨される待機処理:WebDriverWaitの活用

要素数を正確にカウントするための最も堅牢な方法は、WebDriverWaitexpected_conditionsを組み合わせた「明示的な待機」を利用することです。

これにより、「少なくとも1つ以上の要素が表示されるまで待つ」といった柔軟な制御が可能になります。

presence_of_all_elements_locatedの役割

要素数をカウントする前段階として、「少なくとも指定したセレクタに合致する要素がDOM上に現れるまで待機する」処理を挟むのが定石です。

これには、expected_conditions.presence_of_all_elements_locatedを使用します。

このメソッドは、指定した要素が1つ以上見つかった場合に、その要素のリストを返り値として返します。

visibility_of_all_elements_locatedとの違い

似たようなメソッドにvisibility_of_all_elements_locatedがありますが、こちらは「要素がDOMに存在するだけでなく、画面上に表示されている(サイズが0ではない)」ことを条件とします。

ユーザーが目に見える形でリストが表示されるのを待ってからカウントしたい場合は、こちらのメソッドを使用する方が安全です。

一方で、バックグラウンドで読み込まれている隠し要素も含めてカウントしたい場合は、presenceの方を選択しましょう。

【実例】要素数をカウントするPythonプログラム

それでは、実際にWebDriverWaitを使用して、動的に読み込まれるリスト要素の数を正確にカウントするコード例を見ていきましょう。

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

# WebDriverの初期設定(Chromeの例)
driver = webdriver.Chrome()

try:
    # ターゲットサイトへのアクセス
    driver.get("https://example.com/dynamic-list")

    # 最大10秒間、指定した要素が1つ以上現れるまで待機
    # セレクタは適切なものに変更してください
    wait = WebDriverWait(driver, 10)
    elements = wait.until(
        EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".list-item"))
    )

    # 取得したリストの長さを確認
    count = len(elements)
    print(f"検知された要素数: {count}")

    # さらに個別に処理を続けることも可能
    for index, element in enumerate(elements):
        print(f"項目 {index + 1}: {element.text}")

finally:
    # ブラウザを閉じる
    driver.quit()

上記のコードを実行した際の出力イメージは以下の通りです。

実行結果
検知された要素数: 5
項目 1: 商品A
項目 2: 商品B
項目 3: 商品C
項目 4: 商品D
項目 5: 商品E

応用編:特定の要素数になるまで待機する方法

「少なくとも1つ」ではなく、「ちょうど5つになるまで待ちたい」あるいは「前回の読み込みより増えるまで待ちたい」というケースもあります。

標準のexpected_conditionsには「要素数がN個になるまで待つ」という直接的なメソッドはありませんが、カスタム期待条件を自作することで対応可能です。

ラムダ式を用いた柔軟な待機

Pythonのラムダ式(lambda)を利用すると、wait.untilの中に独自の条件式を簡潔に記述できます。

Python
# 要素数が5個になるまで最大10秒待機する
target_count = 5
wait.until(lambda d: len(d.find_elements(By.CSS_SELECTOR, ".list-item")) == target_count)

# 現在の要素数を再取得
final_elements = driver.find_elements(By.CSS_SELECTOR, ".list-item")
print(f"確定した要素数: {len(final_elements)}")

この方法は、スクロールによって追加読み込みが発生する「無限スクロール」の実装などで、「要素が更新されたことを確認してから次の処理へ進む」ために非常に有効です。

待機処理におけるアンチパターン

要素数カウントの実装において、避けるべき手法がいくつか存在します。

これらを知ることで、より効率的でメンテナンス性の高いコードを書くことができます。

time.sleep()による固定時間の待機

最も避けるべきなのは、time.sleep(5)のように秒数を固定して待機する方法です。

ネットワークの状態によって読み込み時間は常に変動するため、5秒待っても足りない場合があれば、1秒で終わるのに4秒無駄にする場合も出てきます。

「固定待機」は処理時間の増大と不安定化の最大の原因となります。

暗黙的な待機(implicitly_wait)への過度な依存

driver.implicitly_wait(10)を設定しておけば、find_elementsも待機してくれると誤解されがちです。

しかし前述の通り、find_elementsは「0個」という結果も「成功」として扱うため、要素が全く存在しないページでは待機が機能せずに空のリストを返して即終了してしまいます。

要素が存在することを確認してからカウントを行うなら、やはり明示的な待機が推奨されます。

要素数カウントと待機方法の比較表

状況に応じて最適な待機方法を選択できるよう、各手法の特徴を以下の表にまとめました。

手法適したシーンメリットデメリット
EC.presence_of_all_elements_located最低1つ以上の要素をカウントしたい時最も標準的で安定している0個であることを確認するのには不向き
ラムダ式 (lambda)特定の数や状態の変化を待ちたい時非常に柔軟な条件設定が可能コードがやや複雑になる
time.sleepデバッグ時の一時的な確認実装が極めて簡単実行速度が低下し、安定性も低い
暗黙的な待機基本的な要素取得の補助一度の設定で全体に適用されるfind_elementsとの相性が悪い

まとめ

Seleniumで要素数を正確にカウントするためには、ブラウザのレンダリング完了を待つ「待機処理」が不可欠です。

基本的には、WebDriverWaitとexpected_conditions(presence_of_all_elements_located)を組み合わせる手法が「正解」と言えます。

これにより、要素がまだ読み込まれていないことによるカウントミスを防ぎ、堅牢な自動化プログラムを構築できます。

もし特定の件数になるまで待ちたい場合は、ラムダ式を活用したカスタム待機を取り入れてみてください。

適切な待機戦略をマスターして、エラーに強く高速なSeleniumスクリプトを実現しましょう。

URLをコピーしました!