- 技術 💻
Selenium Pythonの使い方|要素取得の全パターンと待機処理
Selenium(セレニウム)とは、PythonなどのコードからWebブラウザを自動操作するためのライブラリです。 要素の取得は driver.find_element(By.ID, "title") のように、By で「どの方法で探すか」を指定する書き方が Selenium 4 の基本です。
この記事では、Selenium 4.50.0(2026年10月時点で pip から入る最新版)と Chromium 141 を使い、ローカルのHTMLに対して実際にコードを動かした結果をそのまま載せています。By の全8種の対応表、検索上位で今も見かける旧記法 find_element_by_* がエラーになる再現と書き換え表、つまずきやすい NoSuchElementException・StaleElementReferenceException・iframe の再現と直し方まで、コピペで試せる形でまとめました。
Selenium Pythonの早見表
まずはこの表で「やりたいこと → 書き方」を引けます。 すべて from selenium.webdriver.common.by import By を前提にしています。
| やりたいこと | 書き方(Selenium 4) | 補足 |
|---|---|---|
| ブラウザを起動 | driver = webdriver.Chrome() |
4.6以降は Selenium Manager がドライバーを自動準備 |
| ページを開く | driver.get("https://example.com") |
読み込み完了まで待つ |
| 要素を1つ取得 | driver.find_element(By.ID, "title") |
無ければ NoSuchElementException |
| 要素を全部取得 | driver.find_elements(By.CLASS_NAME, "item") |
無ければ空リスト [] |
| 文字を入力 | el.send_keys("ノートPC") |
消すのは el.clear() |
| クリック | el.click() |
|
| セレクトボックス | Select(el).select_by_value("pc") |
select_by_visible_text / select_by_index も可 |
| テキスト取得 | el.text |
画面に見えている文字 |
| 属性取得 | el.get_attribute("href") |
get_dom_attribute / get_property もある |
| 表示されるまで待つ | WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "x"))) |
明示的な待機 |
| iframe の中を操作 | driver.switch_to.frame("memo-frame") |
戻るときは switch_to.default_content() |
| スクリーンショット | driver.save_screenshot("page.png") |
要素単位は el.screenshot("a.png") |
| ヘッドレス起動 | options.add_argument("--headless=new") |
画面なしで動かす |
| JavaScript 実行 | driver.execute_script("return document.title") |
|
| 終了 | driver.quit() |
ブラウザとドライバーを両方閉じる |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Selenium Pythonの使い方|要素取得の全パターンと待機処理」
動作環境と準備
この記事のコードは、次の環境で実行して確認しています。
| 項目 | バージョン |
|---|---|
| Python | 3.11 |
| selenium | 4.50.0 |
| ブラウザ | Chromium 141.0.7390.37 |
| ChromeDriver | 147.0.7727.24 |
インストール
python3 -m venv .venv
source .venv/bin/activate
pip install selenium
python -c "import selenium; print(selenium.__version__)"
4.50.0
ドライバーの準備は Selenium Manager におまかせできる
Selenium 4.6 以降は、Selenium Manager という仕組みが、インストール済みのブラウザに合う ChromeDriver を自動で用意します。 通常のPCなら、ドライバーを手で入れずに次の2行で起動できます。
from selenium import webdriver
driver = webdriver.Chrome()
ブラウザやドライバーの場所を自分で指定したいとき(社内ネットワークでダウンロードできない、検証用の Chromium を使いたいなど)は、Options と Service で明示します。この記事の検証環境では、Chromium 141 に対して手元の ChromeDriver が 147 だったため、そのままだと次のエラーになりました。
selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only supports Chrome version 147
Current browser version is 141.0.7390.37 with binary path /opt/pw-browsers/chromium-1194/chrome-linux/chrome
ブラウザとドライバーのメジャーバージョンはそろえるのが基本です。 通常は Selenium Manager に任せればそろいます。この記事の検証では、確認用として ChromeDriver の --disable-build-check(バージョン確認を省略するオプション)で起動しています。
共通の起動コード(common.py)
以降のサンプルは、この make_driver() を使います。ブラウザのパスは自分の環境に合わせて変えるか、binary_location と Service(...) の行を消して Selenium Manager に任せてください。
# common.py
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
def make_driver():
options = Options()
options.add_argument("--headless=new") # 画面なしで起動
options.add_argument("--no-sandbox") # コンテナ内で動かす場合
options.add_argument("--window-size=1280,800")
options.binary_location = "/opt/pw-browsers/chromium-1194/chrome-linux/chrome"
service = Service("/opt/node22/bin/chromedriver",
service_args=["--disable-build-check"])
driver = webdriver.Chrome(options=options, service=service)
driver.get(Path("sample.html").resolve().as_uri()) # ローカルHTMLを開く
return driver
練習用のHTML(sample.html)
外部サイトに負荷をかけずに試せるよう、ローカルのHTMLを用意します。備品の検索フォーム、一覧、遅れて表示される要素、iframe を含めています。
<!DOCTYPE html>
<html lang="ja">
<head><meta charset="utf-8"><title>備品管理デモ</title></head>
<body>
<h1 id="title">備品管理デモ</h1>
<form id="search-form">
<input id="keyword" name="q" class="input text" type="text" placeholder="備品名">
<select id="category" name="category">
<option value="">すべて</option>
<option value="pc">パソコン</option>
<option value="desk">机・椅子</option>
</select>
<button id="search-btn" type="button" class="btn primary">検索</button>
</form>
<ul id="items">
<li class="item" data-id="1">ノートPC</li>
<li class="item" data-id="2">モニター</li>
<li class="item" data-id="3">オフィスチェア</li>
</ul>
<a href="#help">使い方ガイドを見る</a>
<div id="result"></div>
<button id="reload-btn" type="button">一覧を再描画</button>
<button id="late-btn" type="button">2秒後に表示</button>
<iframe id="memo-frame" srcdoc="<p id='memo'>iframeの中のメモ</p><input id='memo-input'>"></iframe>
<script>
document.getElementById('search-btn').addEventListener('click', () => {
const q = document.getElementById('keyword').value;
const c = document.getElementById('category').value;
document.getElementById('result').textContent = `検索: ${q} / 分類: ${c}`;
});
document.getElementById('reload-btn').addEventListener('click', () => {
const ul = document.getElementById('items');
ul.innerHTML = '<li class="item" data-id="1">ノートPC</li><li class="item" data-id="2">モニター</li>';
});
document.getElementById('late-btn').addEventListener('click', () => {
setTimeout(() => {
const p = document.createElement('p');
p.id = 'late'; p.textContent = '遅れて出た要素';
document.body.appendChild(p);
}, 2000);
});
</script>
</body>
</html>
要素を取得する8つの方法(By の全種類)
Selenium 4 の要素取得は find_element(By.〇〇, "値") の1つの形にまとまっています。 By には次の8種類があります。
| By の種類 | 探し方 | 例 | 向いている場面 |
|---|---|---|---|
By.ID |
id 属性 | (By.ID, "title") |
id があるなら最優先。速くて確実 |
By.NAME |
name 属性 | (By.NAME, "q") |
フォーム部品 |
By.CLASS_NAME |
class 名(1つだけ) | (By.CLASS_NAME, "item") |
同じ種類の要素をまとめて取る |
By.TAG_NAME |
タグ名 | (By.TAG_NAME, "h1") |
table や li を全部取る |
By.LINK_TEXT |
リンク文字の完全一致 | (By.LINK_TEXT, "使い方ガイドを見る") |
a タグ |
By.PARTIAL_LINK_TEXT |
リンク文字の部分一致 | (By.PARTIAL_LINK_TEXT, "ガイド") |
文言が少し変わるリンク |
By.CSS_SELECTOR |
CSSセレクタ | (By.CSS_SELECTOR, "li.item[data-id='2']") |
属性・親子関係を組み合わせる |
By.XPATH |
XPath | (By.XPATH, "//li[text()='オフィスチェア']") |
文字で探す、親へさかのぼる |
8種類を1つずつ動かす
# by_all.py
from selenium.webdriver.common.by import By
from common import make_driver
driver = make_driver()
print("1 ID :", driver.find_element(By.ID, "title").text)
print("2 NAME :", driver.find_element(By.NAME, "q").get_attribute("placeholder"))
print("3 CLASS_NAME :", len(driver.find_elements(By.CLASS_NAME, "item")), "件")
print("4 TAG_NAME :", driver.find_element(By.TAG_NAME, "h1").text)
print("5 LINK_TEXT :", driver.find_element(By.LINK_TEXT, "使い方ガイドを見る").get_attribute("href").split("#")[1])
print("6 PARTIAL_LINK_TEXT:", driver.find_element(By.PARTIAL_LINK_TEXT, "ガイド").text)
print("7 CSS_SELECTOR :", driver.find_element(By.CSS_SELECTOR, "li.item[data-id='2']").text)
print("8 XPATH :", driver.find_element(By.XPATH, "//li[text()='オフィスチェア']").get_attribute("data-id"))
print("find_elements :", [e.text for e in driver.find_elements(By.CSS_SELECTOR, "#items > li")])
print("0件のfind_elements :", driver.find_elements(By.CLASS_NAME, "not-exist"))
try:
driver.find_element(By.CLASS_NAME, "btn primary")
except Exception as e:
print("複合クラス:", type(e).__name__, str(e).splitlines()[0])
driver.quit()
実行結果(selenium 4.50.0 / Chromium 141):
1 ID : 備品管理デモ
2 NAME : 備品名
3 CLASS_NAME : 3 件
4 TAG_NAME : 備品管理デモ
5 LINK_TEXT : help
6 PARTIAL_LINK_TEXT: 使い方ガイドを見る
7 CSS_SELECTOR : モニター
8 XPATH : 3
find_elements : ['ノートPC', 'モニター', 'オフィスチェア']
0件のfind_elements : []
複合クラス: InvalidSelectorException Message: Compound class names are not allowed.; For documentation on this error, please visit: https://www.selenium.dev/documentation/webdriver/troubleshooting/errors#invalidselectorexception
ポイントは3つです。
find_elements(複数形)は見つからなくても例外にならず、空リストを返します。 「あるかどうか」を調べたいときに便利です。By.CLASS_NAMEにスペース区切りの複数クラスは渡せません。"btn primary"は InvalidSelectorException になります。By.CSS_SELECTOR, ".btn.primary"と書けば取得できます。- 迷ったら「ID → CSS_SELECTOR → XPATH」の順で考えると、読みやすく変更にも強いコードになります。
CSSセレクタとXPathの逆引き
CSS_SELECTOR と XPATH を使いこなすと、ほとんどの要素が取れます。
| 取りたいもの | CSS_SELECTOR | XPATH |
|---|---|---|
| id が title | #title |
//*[@id='title'] |
| class が item の li | li.item |
//li[contains(@class,'item')] |
| 2つのクラスを持つ | .btn.primary |
//*[contains(@class,'btn') and contains(@class,'primary')] |
| 属性の値で | li[data-id='2'] |
//li[@data-id='2'] |
| 属性の前方一致 | a[href^='https'] |
//a[starts-with(@href,'https')] |
| 直下の子 | #items > li |
//*[@id='items']/li |
| n番目 | #items > li:nth-child(2) |
(//*[@id='items']/li)[2] |
| 文字の完全一致 | (不可) | //li[text()='モニター'] |
| 文字の部分一致 | (不可) | //li[contains(text(),'チェア')] |
| 親要素へ戻る | (不可) | //li[text()='モニター']/.. |
文字で探す・親へさかのぼるときだけ XPath、それ以外は CSS という使い分けがわかりやすくおすすめです。
要素の中から探す(絞り込み)
取得した要素に対しても find_element が使えます。範囲を絞ると、同じ class がページ内にいくつもあっても目的の要素だけを取れます。
items = driver.find_element(By.ID, "items")
for li in items.find_elements(By.TAG_NAME, "li"):
print(li.get_attribute("data-id"), li.text)
旧記法 find_element_by_* を書き換える
検索で見つかる記事には find_element_by_id() のような書き方がまだ多く残っていますが、Selenium 4.3.0 でこれらのメソッドは削除されています。 現在のバージョンで実行すると次のようになります。
driver.find_element_by_id("title")
実行結果(selenium 4.50.0):
AttributeError: 'WebDriver' object has no attribute 'find_element_by_id'
AttributeError はメソッドそのものが存在しないという意味です。 次の表のとおり書き換えれば動きます。
| 旧記法(4.3.0で削除) | Selenium 4 の書き方 |
|---|---|
find_element_by_id("x") |
find_element(By.ID, "x") |
find_element_by_name("x") |
find_element(By.NAME, "x") |
find_element_by_class_name("x") |
find_element(By.CLASS_NAME, "x") |
find_element_by_tag_name("x") |
find_element(By.TAG_NAME, "x") |
find_element_by_link_text("x") |
find_element(By.LINK_TEXT, "x") |
find_element_by_partial_link_text("x") |
find_element(By.PARTIAL_LINK_TEXT, "x") |
find_element_by_css_selector("x") |
find_element(By.CSS_SELECTOR, "x") |
find_element_by_xpath("x") |
find_element(By.XPATH, "x") |
find_elements_by_〇〇("x") |
find_elements(By.〇〇, "x") |
webdriver.Chrome("chromedriver") |
webdriver.Chrome(service=Service("chromedriver")) |
options.headless = True |
options.add_argument("--headless=new") |
書き換えのコツは「_by_xxx を消して、第1引数に By.XXX を足す」だけです。 from selenium.webdriver.common.by import By の import を忘れずに追加してください。
よくあるエラーを再現して直す
Selenium のつまずきは、ほとんどが「まだ表示されていない」「取り直しが必要」「iframe の中にある」の3つです。 まとめて再現するコードを用意しました。
# errors.py
import time
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 (
NoSuchElementException, StaleElementReferenceException, TimeoutException)
from common import make_driver
driver = make_driver()
# 1. 遅れて表示される要素
driver.find_element(By.ID, "late-btn").click()
try:
driver.find_element(By.ID, "late")
except NoSuchElementException as e:
print("[待機なし]", type(e).__name__, ":", e.msg.splitlines()[0])
t = time.perf_counter()
late = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.ID, "late")))
print(f"[WebDriverWait] {late.text} ({time.perf_counter()-t:.1f}秒待った)")
try:
WebDriverWait(driver, 1).until(EC.presence_of_element_located((By.ID, "never")))
except TimeoutException as e:
print("[タイムアウト]", type(e).__name__)
# 2. 画面が書き換わった後の古い要素
first = driver.find_element(By.CSS_SELECTOR, "#items li")
driver.find_element(By.ID, "reload-btn").click()
try:
print(first.text)
except StaleElementReferenceException as e:
print("[Stale]", type(e).__name__, ":", e.msg.splitlines()[0])
first = driver.find_element(By.CSS_SELECTOR, "#items li")
print("[取り直し]", first.text)
# 3. iframe の中の要素
try:
driver.find_element(By.ID, "memo")
except NoSuchElementException as e:
print("[iframe 切替なし]", type(e).__name__)
WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "memo-frame")))
print("[iframe 切替後]", driver.find_element(By.ID, "memo").text)
driver.find_element(By.ID, "memo-input").send_keys("メモ入力OK")
print("[iframe 入力]", driver.find_element(By.ID, "memo-input").get_attribute("value"))
driver.switch_to.default_content()
print("[元に戻る]", driver.find_element(By.ID, "title").text)
# 4. 暗黙の待機
driver.implicitly_wait(3)
t = time.perf_counter()
try:
driver.find_element(By.ID, "never")
except NoSuchElementException:
print(f"[implicitly_wait(3)] 見つからず {time.perf_counter()-t:.1f}秒で例外")
driver.quit()
実行結果:
[待機なし] NoSuchElementException : no such element: Unable to locate element: {"method":"css selector","selector":"[id="late"]"}
[WebDriverWait] 遅れて出た要素 (2.1秒待った)
[タイムアウト] TimeoutException
[Stale] StaleElementReferenceException : stale element reference: stale element not found in the current frame
[取り直し] ノートPC
[iframe 切替なし] NoSuchElementException
[iframe 切替後] iframeの中のメモ
[iframe 入力] メモ入力OK
[元に戻る] 備品管理デモ
[implicitly_wait(3)] 見つからず 3.0秒で例外
なお、エラーメッセージを見ると By.ID も内部では CSS セレクタ [id="late"] に変換されて検索されていることがわかります。
エラー別の原因と直し方
| エラー | 主な原因 | 直し方 |
|---|---|---|
NoSuchElementException |
まだ表示されていない/セレクタの書き間違い/iframe の中 | WebDriverWait で待つ。DevTools でセレクタを確認。iframe なら切り替え |
TimeoutException |
待ったが条件を満たさなかった | 条件(表示・クリック可能など)とセレクタを見直す。待ち時間を調整 |
StaleElementReferenceException |
取得後に画面が書き換わり、要素が作り直された | 操作の直前に取り直す |
InvalidSelectorException |
By.CLASS_NAME に複数クラス、XPath の文法ミス |
By.CSS_SELECTOR, ".a.b" に変える |
ElementClickInterceptedException |
別の要素(ダイアログ・固定ヘッダー)が上に重なっている | EC.element_to_be_clickable で待つ、スクロールする |
ElementNotInteractableException |
非表示の要素を操作しようとした | EC.visibility_of_element_located で表示を待つ |
AttributeError: ... find_element_by_id |
旧記法 | 前の章の書き換え表で By を使う |
待機は WebDriverWait(明示的な待機)を基本にする
Selenium の待ち方は、time.sleep()・暗黙の待機・明示的な待機の3つです。
| 待ち方 | 書き方 | 特徴 | おすすめ度 |
|---|---|---|---|
| 固定時間 | time.sleep(3) |
必ず3秒止まる。早く表示されても待つ | 調査用 |
| 暗黙の待機 | driver.implicitly_wait(3) |
全 find_element に最大3秒の待ちが付く。見つからないと毎回3秒かかる |
小さなスクリプト向け |
| 明示的な待機 | WebDriverWait(driver, 10).until(条件) |
条件を満たした瞬間に進む。条件を選べる | 基本はこれ |
上の実行結果でも、WebDriverWait は2秒後に表示された時点ですぐ進み(2.1秒)、暗黙の待機は見つからない要素に対して毎回3.0秒かかっています。Selenium の公式ドキュメントでも、暗黙の待機と明示的な待機を混ぜると待ち時間が読みにくくなるため、混在させないことが案内されています。
よく使う expected_conditions
from selenium.webdriver.support import expected_conditions as EC で使える主な条件です。
| 条件 | 意味 | 戻り値 |
|---|---|---|
presence_of_element_located(loc) |
DOM に存在する(見えなくてもよい) | 要素 |
visibility_of_element_located(loc) |
表示されている | 要素 |
element_to_be_clickable(loc) |
表示され、有効でクリックできる | 要素 |
presence_of_all_elements_located(loc) |
1つ以上存在する | 要素のリスト |
text_to_be_present_in_element(loc, "文字") |
指定の文字が含まれる | True |
invisibility_of_element_located(loc) |
消えた(読み込み中表示が消えるのを待つ) | True など |
frame_to_be_available_and_switch_to_it(loc) |
iframe が使えるようになったら切り替え | True |
title_contains("文字") |
タイトルに文字が含まれる | True |
url_contains("/done") |
URL に文字が含まれる | True |
staleness_of(el) |
古い要素が DOM から外れた(画面遷移の完了確認) | True |
alert_is_present() |
アラートが出た | Alert |
クリックの前は element_to_be_clickable、文字を読む前は visibility_of_element_located と覚えておくと、ほとんどの場面に対応できます。
wait = WebDriverWait(driver, 10)
btn = wait.until(EC.element_to_be_clickable((By.ID, "search-btn")))
btn.click()
wait.until(EC.text_to_be_present_in_element((By.ID, "result"), "検索:"))
iframe の切り替え方
iframe(ページの中に埋め込まれた別のページ)の中の要素は、切り替えないと見つかりません。
| やりたいこと | 書き方 |
|---|---|
| id / name で切り替え | driver.switch_to.frame("memo-frame") |
| 要素で切り替え | driver.switch_to.frame(driver.find_element(By.CSS_SELECTOR, "iframe")) |
| 番号で切り替え | driver.switch_to.frame(0) |
| 待ってから切り替え | WebDriverWait(driver, 5).until(EC.frame_to_be_available_and_switch_to_it((By.ID, "memo-frame"))) |
| 1つ外側へ | driver.switch_to.parent_frame() |
| ページ全体へ戻る | driver.switch_to.default_content() |
操作が終わったら default_content() で戻すのを忘れないようにしましょう。戻さないと、外側の要素が NoSuchElementException になります。
入力・クリック・セレクトボックス・スクショの使い方
要素を取れたら、あとは操作メソッドを呼ぶだけです。 よく使う操作をまとめて動かします。
# ops.py
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from common import make_driver
driver = make_driver()
print("タイトル:", driver.title)
# 文字入力(全選択して消してから入力)
box = driver.find_element(By.ID, "keyword")
box.send_keys("モニター")
box.send_keys(Keys.CONTROL, "a")
box.send_keys(Keys.BACK_SPACE)
box.send_keys("ノートPC")
print("入力値:", box.get_attribute("value"))
# セレクトボックス
select = Select(driver.find_element(By.ID, "category"))
select.select_by_value("pc")
print("選択中:", select.first_selected_option.text)
select.select_by_visible_text("机・椅子")
print("選択中:", select.first_selected_option.text)
select.select_by_index(1)
print("選択肢:", [o.text for o in select.options])
# クリック
driver.find_element(By.ID, "search-btn").click()
print("結果:", driver.find_element(By.ID, "result").text)
# 情報の取得
item = driver.find_element(By.CSS_SELECTOR, "li.item")
print("text / data-id / tag / 表示 :", item.text, item.get_attribute("data-id"), item.tag_name, item.is_displayed())
print("dom_attribute / dom_property :", box.get_dom_attribute("placeholder"), box.get_property("value"))
# スクリーンショット
driver.save_screenshot("page.png")
driver.find_element(By.ID, "search-form").screenshot("form.png")
driver.execute_script("window.scrollTo(0, document.body.scrollHeight)")
print("スクショ保存: page.png, form.png")
driver.quit()
実行結果:
タイトル: 備品管理デモ
入力値: ノートPC
選択中: パソコン
選択中: 机・椅子
選択肢: ['すべて', 'パソコン', '机・椅子']
結果: 検索: ノートPC / 分類: pc
text / data-id / tag / 表示 : ノートPC 1 li True
dom_attribute / dom_property : 備品名 ノートPC
スクショ保存: page.png, form.png
保存された画像のサイズを確認すると、page.png は 1280×661(表示領域の大きさ)、form.png はフォーム部分だけの 1264×24 でした。save_screenshot は表示中の範囲、要素.screenshot はその要素だけを撮ります。
操作メソッドの一覧
| 分類 | メソッド | 内容 |
|---|---|---|
| 入力 | send_keys("文字") |
文字を入力 |
| 入力 | send_keys(Keys.ENTER) |
特殊キー(ENTER, TAB, ESCAPE など) |
| 入力 | clear() |
入力欄を空にする |
| 入力 | send_keys("/path/file.png") |
input type="file" へのファイル指定 |
| クリック | click() |
クリック |
| クリック | submit() |
フォーム送信 |
| 取得 | text |
表示されている文字 |
| 取得 | get_attribute("x") |
属性(なければプロパティ)の値 |
| 取得 | get_dom_attribute("x") |
HTML に書かれた属性の値 |
| 取得 | get_property("x") |
現在のプロパティの値(入力後の value など) |
| 状態 | is_displayed() / is_enabled() / is_selected() |
表示・有効・選択の状態 |
| 画面 | driver.title / driver.current_url / driver.page_source |
タイトル・URL・HTML |
| 画面 | driver.back() / forward() / refresh() |
戻る・進む・再読み込み |
| ウィンドウ | driver.window_handles / switch_to.window(h) |
タブの切り替え |
| アラート | driver.switch_to.alert.accept() |
OK を押す |
マウス操作(ホバー・ドラッグ)は ActionChains
マウスを重ねる・ドラッグするといった操作は ActionChains で組み立てます。
from selenium.webdriver.common.action_chains import ActionChains
menu = driver.find_element(By.ID, "title")
ActionChains(driver).move_to_element(menu).perform() # ホバー
ActionChains(driver).double_click(menu).perform() # ダブルクリック
ActionChains(driver).context_click(menu).perform() # 右クリック
# ActionChains(driver).drag_and_drop(src, dst).perform() # ドラッグ&ドロップ
※ この記事の検証では move_to_element(ホバー)で mouseover イベントが発生することを確認しました。ドラッグ&ドロップなどその他の操作は、公式ドキュメントで確認してください。
ヘッドレスで動かす
ヘッドレスとは、ブラウザの画面を表示せずに動かすモードです。 サーバーや CI で動かすときに使います。Chrome / Chromium では --headless=new を指定します(以前の options.headless = True は現在のバージョンでは使えません)。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless=new")
options.add_argument("--window-size=1280,800") # ヘッドレスでも画面サイズを決めておく
driver = webdriver.Chrome(options=options)
| オプション | 用途 |
|---|---|
--headless=new |
画面なしで起動 |
--window-size=1280,800 |
スクショやレイアウトのサイズを固定 |
--no-sandbox |
Docker などのコンテナ内で起動するとき |
--disable-dev-shm-usage |
コンテナの共有メモリが小さいとき |
--lang=ja-JP |
表示言語を日本語に |
ヘッドレスでは画面サイズが小さめになることがあるため、--window-size を付けておくとスクショや要素の表示が安定します。
完成形:検索して結果を取り出すスクリプト
ここまでの内容を1つにまとめた、コピペで動く完成形です。 with 文を使うと、途中でエラーになってもブラウザが閉じられます。
# search_items.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait, Select
from selenium.webdriver.support import expected_conditions as EC
from common import make_driver
with make_driver() as driver:
wait = WebDriverWait(driver, 10)
box = wait.until(EC.visibility_of_element_located((By.ID, "keyword")))
box.clear()
box.send_keys("ノートPC")
Select(driver.find_element(By.ID, "category")).select_by_value("pc")
wait.until(EC.element_to_be_clickable((By.ID, "search-btn"))).click()
wait.until(EC.text_to_be_present_in_element((By.ID, "result"), "検索:"))
print(driver.find_element(By.ID, "result").text)
rows = [(li.get_attribute("data-id"), li.text)
for li in driver.find_elements(By.CSS_SELECTOR, "#items > li")]
print(rows)
実行結果:
検索: ノートPC / 分類: pc
[('1', 'ノートPC'), ('2', 'モニター'), ('3', 'オフィスチェア')]
Seleniumを使うときの心がけ
外部のサイトを自動操作・データ取得するときは、そのサイトの利用規約と robots.txt を確認し、アクセス間隔をあけて相手のサーバーに負担をかけないようにしましょう。 ログインが必要なページや、自動取得を禁止しているページは対象にしないのが基本です。
また、目的によって道具を選ぶと作業が楽になります。
| 目的 | 向いている道具 |
|---|---|
| JavaScript で描画されるページの操作・入力 | Selenium |
| 静的なHTMLからデータを取り出すだけ | requests + BeautifulSoup(別記事で解説) |
| E2Eテスト、自動待機を重視 | Playwright(別記事で解説) |
| 複数ブラウザ・既存の Selenium 資産を活用 | Selenium(Grid で並列実行も可能) |
よくある質問
Q. webdriver.Chrome() で SessionNotCreatedException が出ます。
A. ブラウザと ChromeDriver のバージョンが合っていないことが多いです。PATH に古い chromedriver が残っていると、それが使われることがあります。古い chromedriver を PATH から外し、Selenium Manager に任せるとそろったドライバーが使われます。
Q. find_element と find_elements はどう使い分けますか?
A. 必ずある1つの要素は find_element、0個かもしれない・複数ある要素は find_elements です。find_elements は見つからなくても空リストを返すので、if driver.find_elements(...): で存在チェックができます。
Q. time.sleep() ではいけませんか?
A. 動きはしますが、表示が早くても必ずその秒数だけ待つため、全体が遅くなりがちです。WebDriverWait なら条件を満たした瞬間に進むので、速さと安定性を両立できます。
Q. get_attribute と get_property の違いは?
A. get_dom_attribute は HTML に書かれた値、get_property は現在の値です。入力欄に文字を入れたあとの value は get_property("value") で取れます。get_attribute は両方を見て値を返す便利メソッドです。
まとめ
- Selenium 4 の要素取得は
find_element(By.〇〇, "値")に統一。By は ID / NAME / CLASS_NAME / TAG_NAME / LINK_TEXT / PARTIAL_LINK_TEXT / CSS_SELECTOR / XPATH の8種類 - 旧記法
find_element_by_*は 4.3.0 で削除済み。_by_xxxを消してBy.XXXを足せば書き換えられる - 複数クラスは
By.CSS_SELECTOR, ".a.b"、文字や親で探すときは XPath - 待機は
WebDriverWait+expected_conditionsが基本。暗黙の待機と混ぜない - Stale は操作の直前に取り直す、iframe は
switch_to.frameで切り替えてdefault_contentで戻る - ドライバーは Selenium Manager におまかせ。ヘッドレスは
--headless=new - 外部サイトでは利用規約と robots.txt を確認し、間隔をあけてアクセスする
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Selenium Pythonの使い方|要素取得の全パターンと待機処理」
株式会社RJCでは、Seleniumによるブラウザ自動操作の知識を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。