Pythonを用いたWebブラウザ自動化ライブラリであるSeleniumは、2026年現在もWebスクレイピングやUI自動テストの現場において中心的な役割を果たしています。
Webサイトの構造が複雑化し、シングルページアプリケーション (SPA) やWebコンポーネントが一般化した現代において、目的の要素を正確に、そして安定して取得する技術は、エンジニアにとって必須のスキルといえます。
その中でも、特定のHTML要素を特定して操作を行うfind_elementメソッドは、自動化プログラムを構築する上でもっとも基本的かつ重要な機能です。
本記事では、Seleniumを用いた要素取得の基礎から、エラーを回避するための実践的なテクニック、そして最新のWeb標準に対応した高度な指定方法までを詳しく解説します。
Python Seleniumにおける要素取得の役割
ブラウザ上の操作を自動化するためには、まず「どのボタンをクリックするのか」「どの入力ボックスにテキストを入力するのか」をプログラムに教える必要があります。
この「対象を特定する作業」が要素取得です。
Selenium 4.0以降、要素取得のインターフェースは整理され、find_element メソッドに統一されました。
このメソッドを使いこなすことで、複雑なDOM構造の中からピンポイントで要素を抽出することが可能になります。
しかし、単に名前を知っているだけでは不十分です。
動的なコンテンツの変化や通信遅延によって要素が見つからないといったトラブルに直面した際、適切な回避策を講じられるかどうかが、実用的なスクリプトを書けるかどうかの分かれ目となります。
find_elementの基本構文とByクラスの利用
Seleniumで要素を取得する際の基本的な書式は、driver.find_element(By.ロケータの種類, "値") という形をとります。
以前の古いバージョンで使用されていた find_element_by_id といった個別メソッドは推奨されず、現在は By クラスを利用する方法が標準です。
まず、プログラムの冒頭で以下のインポートを行う必要があります。
from selenium.webdriver.common.by import By
この By クラスには、要素を特定するための様々な戦略 (ロケータ) が定義されています。
主なロケータの種類を以下の表にまとめます。
| ロケータ種別 | 記述方法 | 特徴・用途 |
|---|---|---|
| By.ID | (By.ID, "element-id") | ID属性で指定。ページ内で一意であるため最も高速で確実。 |
| By.NAME | (By.NAME, "element-name") | name属性で指定。フォームの入力項目などで多用される。 |
| By.CLASS_NAME | (By.CLASS\_NAME, "btn-primary") | class属性で指定。スタイルに基づいて要素を探す際に便利。 |
| By.TAG_NAME | (By.TAG\_NAME, "h1") | HTMLタグ名で指定。特定のタグをまとめて扱う際に使用。 |
| By.LINK_TEXT | (By.LINK\_TEXT, "詳細はこちら") | リンクのテキストが完全に一致する要素を取得。 |
| By.PARTIAL_LINK_TEXT | (By.PARTIAL\_LINK\_TEXT, "詳細") | リンクテキストの一部が含まれる要素を取得。 |
| By.CSS_SELECTOR | (By.CSS\_SELECTOR, ".main > p") | CSSセレクタで指定。柔軟性が高く、実行速度も速い。 |
| By.XPATH | (By.XPATH, "//div[@id='root']//button") | XPathで指定。非常に強力だが、記述が複雑になりがち。 |
IDやNameによる直接指定
最も推奨されるのは By.ID です。
HTML設計が適切であれば、IDはページ内で重複しないため、誤った要素を取得するリスクが極めて低くなります。
また、ブラウザエンジンの最適化により、要素の検索スピードが最も速いというメリットもあります。
一方、システムが自動生成する動的なID (例: id="ember123") の場合は、実行のたびに値が変わるため ID 指定は使えません。
その場合は他のロケータを検討します。
CSSセレクタとXPathの使い分け
複雑な構造のサイトでは、By.CSS_SELECTOR または By.XPATH を活用します。
CSSセレクタは、フロントエンドエンジニアにとって馴染み深く、記述が簡潔になる傾向があります。
一方、XPathは「親要素に遡って検索する」といった、CSSセレクタでは不可能な複雑な条件指定が可能です。
一般的には、読みやすさとメンテナンス性を重視してCSSセレクタを第一候補とし、どうしても実現できない場合のみXPathを使用するという優先順位が推奨されます。
実践的な要素取得のコード例
ここでは、実際のWebサイトを想定した要素取得のコード例を紹介します。
例えば、ログイン画面でユーザー名を入力し、送信ボタンをクリックする一連の流れは以下のようになります。
from selenium import webdriver
from selenium.webdriver.common.by import By
# ブラウザの起動 (Chromeを例に)
driver = webdriver.Chrome()
try:
# 対象のWebサイトにアクセス
driver.get("https://example.com/login")
# 1. IDを使ってユーザー名入力欄を取得
username_field = driver.find_element(By.ID, "user_login")
username_field.send_keys("test_user")
# 2. Nameを使ってパスワード入力欄を取得
password_field = driver.find_element(By.NAME, "user_password")
password_field.send_keys("secure_password123")
# 3. CSSセレクタを使ってログインボタンを取得
login_button = driver.find_element(By.CSS_SELECTOR, "button.submit-btn")
login_button.click()
print("要素の取得と操作に成功しました")
finally:
# ブラウザを閉じる
driver.quit()
このコードでは、異なるロケータを組み合わせて効率的に要素を特定しています。
要素取得に失敗した場合は、後述する例外が発生するため、実運用では try-except ブロックや待機処理を組み合わせることが一般的です。
find_element と find_elements の決定的な違い
要素取得メソッドには、単数形の find_element と複数形の find_elements の2種類があります。
これらを正しく使い分けることは、堅牢なスクリプトを書く上で非常に重要です。
find_element (単数形)
- 条件に合致する要素のうち、最初に見つかった1つだけを返します。
- 要素が見つからなかった場合、NoSuchElementException というエラーを発生させ、プログラムが停止します。
- 単一のボタンや入力欄など、「必ず存在しているはずの要素」を操作する際に適しています。
find_elements (複数形)
- 条件に合致するすべての要素を リスト形式 で返します。
- 要素が見つからなかった場合でもエラーにはならず、空のリスト [ ] を返します。
- 複数の検索結果を順番に処理したい場合や、要素が存在するかどうかのチェックをエラーなしで行いたい場合に適しています。
例えば、特定の広告ポップアップが表示されているときだけ閉じたい、という処理を書く場合、find_elements を使ってリストの長さが0より大きいかどうかを確認することで、エラーを回避しつつ柔軟な条件分岐が可能になります。
要素が見つからない場合のエラー対処法
Seleniumを扱っていると必ずと言っていいほど遭遇するのが NoSuchElementException です。
このエラーが発生する主な原因は、指定したロケータが間違っているか、あるいは「要素が表示される前に取得しようとした」かのどちらかです。
1. ロケータの再確認
まず、ブラウザの開発者ツール (F12キー) を開き、指定したIDやクラス名が正しいか、スペルミスがないかを確認してください。
2026年現在のモダンなWebサイトでは、要素のクラス名がビルドのたびにランダムに変わる (CSS Modulesなど) ケースが増えています。
その場合は、不変な属性や、要素の包含関係を利用した相対的な指定に切り替える必要があります。
2. 待機処理の導入 (Explicit Wait)
要素がDOM上に存在するものの、JavaScriptの実行待ちなどでまだ画面に出ていない場合、即座に find_element を実行すると失敗します。
これを解決するのが「待機処理」です。
もっとも推奨されるのは、特定の条件を満たすまで待つ 明示的な待機 (Explicit Wait) です。
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 最大10秒間、要素がクリック可能になるまで待機
wait = WebDriverWait(driver, 10)
element = wait.until(EC.element_to_be_clickable((By.ID, "dynamic-button")))
element.click()
このように、WebDriverWait を使用することで、ネットワークの遅延やレンダリングの重さに左右されない、「安定した要素取得」が可能になります。
複雑なDOM構造へのアプローチ
Web技術の進化に伴い、標準的な find_element だけでは取得が困難な要素も増えています。
Shadow DOM内の要素取得
Webコンポーネントで利用される Shadow DOM 内の要素は、通常の find_element では検索できません。
まずホストとなる要素を取得し、その shadow_root プロパティを介して内部を探索する必要があります。
# Shadow Hostを取得
shadow_host = driver.find_element(By.CSS_SELECTOR, "#shadow-root-element")
# Shadow Rootを取得
shadow_root = shadow_host.shadow_root
# Shadow Root内から要素を検索
inner_element = shadow_root.find_element(By.CSS_SELECTOR, ".inner-button")
iframe内の要素取得
別のHTMLドキュメントを埋め込んでいる iframe も注意が必要です。
内部の要素を取得するには、まずドライバの操作対象をそのフレームに切り替える必要があります。
# iframeにスイッチ
iframe = driver.find_element(By.ID, "login-frame")
driver.switch_to.frame(iframe)
# iframe内の要素を操作
driver.find_element(By.ID, "inner-id").send_keys("data")
# 操作が終わったら親のコンテキストに戻す
driver.switch_to.default_content()
このように、対象となる要素がどの「層」にあるのかを理解することが、要素取得を成功させる鍵となります。
要素取得を安定させるためのベストプラクティス
エラーが少なく、メンテナンスしやすいスクリプトを作成するための指針をいくつか挙げます。
セレクタの簡潔さを保つ
XPathをコピー&ペーストすると、/html/body/div[1]/div[2]/form/div[3]/input のような絶対パスになりがちです。
しかし、これはサイトの構造が少し変わるだけで動作しなくなります。
「なるべく短く、意味のある属性を利用したセレクタ」を書くように心がけましょう。
テスト専用の属性を付与する
もしあなたがWebサイトの開発チームと連携できる立場にあるなら、テストや自動化のために専用の属性 (例: data-testid="login-submit") をHTMLに付与してもらうのが最も理想的です。
デザインの変更に左右されず、常に同じロケータで要素を特定できるようになります。
StaleElementReferenceException への理解
要素を取得した後にページの一部が更新されると、一度取得した変数としての要素は「古くなった (Stale)」とみなされ、操作時にエラーが発生します。
この場合は、再度 find_element を実行して要素を取り直す必要があります。
まとめ
Python Seleniumにおける要素取得は、自動化の成否を分ける極めて重要な工程です。
find_element メソッドを核として、適切なロケータを選択し、明示的な待機を組み合わせることで、エラーに強い堅牢なプログラムを構築することができます。
- Byクラスを適切に使い分け、可能な限りIDやCSSセレクタを利用する。
- 単一の要素取得には
find_element、存在確認やリスト処理にはfind_elementsを使う。 WebDriverWaitを活用し、ページの読み込み完了を待つ仕組みを取り入れる。- Shadow DOM や iframe など、特殊な構造がある場合は操作対象を適切に切り替える。
これらの知識を土台として、実際のWebサイトでコードを書きながら、状況に応じた最適な取得戦略を身につけていってください。
安定した要素取得ができるようになれば、ブラウザ自動化の可能性はより一層広がります。
