Requestsで受け取ったHTMLには目的の値がないのに、ブラウザーでボタンを押すと表示されるページがあります。Seleniumはブラウザーを操作できるため、クリック後の状態を待って読む用途に使えます。
ただし、単純なHTMLの取得だけで済む場合は、ブラウザーを起動する必要はありません。Seleniumを使うときは、何の状態になったら次へ進むかを、待機条件にします。
手元のボタンで動きを確かめる
次をdynamic-example.htmlとしてUTF-8で保存します。クリックから少し後に文字が出る架空のページです。外部への通信やフォーム送信はありません。
<!doctype html>
<html lang="ja">
<head><meta charset="utf-8"><title>待機の練習</title></head>
<body>
<button id="load" type="button">表示する</button>
<p id="result" hidden></p>
<script>
document.querySelector('#load').addEventListener('click', () => {
setTimeout(() => {
const result = document.querySelector('#result');
result.textContent = '準備できました';
result.hidden = false;
}, 150);
});
</script>
</body>
</html>
seleniumが使えるPythonと、対応するブラウザー・ドライバーを用意します。この例では、既に手元にある二つの実行ファイルを引数で指定し、自動取得に任せない形にしています。ブラウザーとドライバーの互換性は、それぞれの案内で確認します。
表示されるまで待って読む
次をselenium-example.pyとして、HTMLと同じフォルダーへ保存します。
import sys
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
browser_path, driver_path = sys.argv[1:3]
options = webdriver.ChromeOptions()
options.binary_location = browser_path
options.add_argument("--headless=new")
driver = webdriver.Chrome(service=Service(driver_path), options=options)
try:
page = Path("dynamic-example.html").resolve().as_uri()
driver.get(page)
driver.find_element(By.ID, "load").click()
def ready(browser):
result = browser.find_element(By.ID, "result")
return result.is_displayed() and result.text == "準備できました"
WebDriverWait(driver, 10).until(ready)
print(driver.find_element(By.ID, "result").text)
finally:
driver.quit()
実行時には次の二つのパスを手元の実行ファイルへ読み替えます。空白を含むパスも一つの引数として渡せるよう、引用符で囲みます。
py selenium-example.py "ブラウザーの絶対パス" "ドライバーの絶対パス"
成功時には「準備できました」と表示されます。この例はPython 3.12.10、Selenium 4.39.0、既存のChromium 143と対応するChromeDriverでローカル実行を確認しました。外部サイトは操作していません。最大10秒はこの例の待機設定です。ページの読み込みに成功しただけで、結果の文字も出たとは判断していません。
固定秒数の待機と条件の待機
time.sleepで長く待つだけでは、早く表示されても待ち続け、遅い場合は読み取りに失敗します。この例では、結果要素が表示され、期待する文字になったことを明示的に待ちます。
Seleniumには要素検索の暗黙的な待機もありますが、公式資料は暗黙的待機と明示的待機を混ぜると待ち時間が予測しにくくなることを説明しています。このコードでは暗黙的待機を追加していません。
閉じる処理と実サイトでの範囲
finallyでquitを呼び、途中で例外が起きてもブラウザーの終了処理へ進むようにしています。既存のユーザープロファイルは指定していないため、普段のログイン済み画面を操作する例でもありません。
実サイトへ置き換える場合は、対象の利用条件と操作権限を確認します。ログイン、購入、送信などの操作を、取得用のクリックと同じ扱いで自動化しないようにします。ローカルのボタンで動いた確認と、実サービス上の取得・操作が許可されている確認を分けて進めます。
関連する作業
ブラウザー操作の別の例と、HTTP取得だけで済む場合のコードを比較できます。
