TECHNOLOGY

Seleniumの基本操作:PythonでWebブラウザを自動操作する方法

Seleniumは、Webブラウザを自動操作するためのツールで、主にブラウザの自動テストに使用されます。指定したスクリプトに従って、クリックやテキスト入力などの操作を自動化することで、テスト作業を効率化できます。これにより、コストを抑えつつテストの実行頻度を増やし、バグの早期発見に役立ちます。特に、チーム開発において各メンバーが統一されたテストを実施することで、不具合の原因の切り分けを容易にし、安定した開発プロセスを確立できます。また、単調なテスト作業を自動化することで、モチベーションの低下を防ぐ効果もあります。

さらに、SeleniumはWebスクレイピングにも活用されています。近年のウェブサイトではJavascriptを用いた動的なコンテンツ生成が増えており、通常のHTML取得では必要な情報を取得できないことがあります。Seleniumを使うことで、実際にブラウザを操作し、ページが完全に表示された状態のHTMLを取得することができ、必要な情報を収集できる可能性が高まります。

本記事では、Pythonでブラウザを自動するためのSeleniumの基本的な使用方法について、ご紹介いたします。

本記事で使用した環境は以下になります。

・ Windows 11
・ Python 3.13.0
・ selenium 4.29.0
・ webdriver-manager 4.0.2

目次

Seleniumの概要

Seleniumは、Webアプリケーションの画面操作を自動化するためのツールです。クリックやキー入力などブラウザに対するさまざまな操作を行うことができます。SeleniumはApachi License 2.0で提供されており、だれでも無料で使用することができます。また、さまざまなOSやブラウザに対応しています。対応しているOSやブラウザの主なものを以下に示します。

項目対応状況
対応しているブラウザGoogle Chrome
Mozilla Firefox
Microsoft Edge
Safari(macOS専用)
Opera
動作するOSWindows
MacOS X
Linux
iOS
Android
対応しているプログラミング言語Java
JavaScript
Python
Ruby
C#

Selenium単体ではブラウザを操作することはできず、各ブラウザごとに専用のWebDriverが必要になります。WebdriverはSeleniumのスクリプトとブラウザの間で仲介の役割をはたします。Seleniumのコードをブラウザの操作に変換し、ブラウザを開く、操作する、閉じるなどの指示を実行します。

Seleniumの環境構築

本記事では、PythonによりSeleniumを使用します。そのために、次のパッケージをインストールします。

pip install selenium
pip install webdriver-manager

ここで、webdriver-mangaerは、SeleniumでWebDriverを自動でインストール・管理するためのPythonのパッケージです。

通常、Seleniumを使うには手動でWebDriverをダウンロードしてパスを設定する必要がありますが、webdriver-managerを使えば、バージョン管理を自動化できるので手間が省けます。

項目通常のWebDriverwebdriver-mangaer
WebDriverのダウンロード手動自動
バージョン管理手動で確認自動で最新バージョンを取得
OS対応自分で対応版を取得OSに応じて適切なバージョンを取得
コードの簡潔さ設定が面倒1行でセットアップ可能

テスト用のHTMLファイル

Seleniumの機能をテストするために次のHTMLファイルを使用します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Selenium テストページ</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .container { width: 600px; margin: 0 auto; }
        .hidden { display: none; }
        .fade-in { opacity: 0; transition: opacity 1s; }
        .fade-in.visible { opacity: 1; }
        iframe { width: 100%; height: 120px; border: 1px solid black; }
        .shadow-container { margin-top: 20px; }
        .long-page { height: 1200px; background: linear-gradient(to bottom, white, lightgray); }
        .drop-zone { width: 100%; height: 50px; border: 2px dashed gray; display: flex; align-items: center; justify-content: center; margin-top: 10px; }
    </style>
</head>
<body>
    <div class="container">
        <h1>Seleniumテストページ</h1>
        <!--  基本フォーム -->
        <h2>ユーザーリスト</h2>
        <label>名前: <input type="text" id="name" value="Anonymous"></label></br>
        </br>

        <!-- チェックボックス -->
        <label><input type="checkbox" id="agree"> 規約に同意する</label>

        <!-- ラジオボタン -->
        <label>性別:</label>
        <label><input type="radio" name="gender" value="male"> 男性</label>
        <label><input type="radio" name="gender" value="female"> 女性</label>

        <!-- ドロップダウン -->
        <label for="country">国を選択:</label>
        <select id="country">
            <option value="jp">日本</option>
            <option value="us">アメリカ</option>
            <option value="uk">イギリス</option>
        </select>

        <!-- JavaScriptで新規要素追加 -->
        <br><br>
        <button id="add_user">新しいユーザーを追加</button>
        <br><br>

        <!-- テーブル -->
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>名前</th>
                    <th>性別</th>
                    <th>国籍</th>
                    <th>アクション</th>
                </tr>
            </thead>
            <tbody id="user_table">
                <tr>
                    <td>1</td>
                    <td>田中太郎</td>
                    <td>男性</td>
                    <td>日本</td>
                    <td></td>
                </tr>
                <tr>
                    <td>2</td>
                    <td>山田花子</td>
                    <td>女性</td>
                    <td>日本</td>
                    <td></td>
                </tr>
            </tbody>
        </table>         

        <!--  動的なリスト(掲示板シミュレーション) -->
        <h2>掲示板(動的要素)</h2>
        <ul id="post_list"></ul>
        <button id="add_post">新しい投稿を追加</button>

        <!--  アラートダイアログ -->
        <button id="alert_button">アラートを表示</button>

        <!--  10秒後に表示されるボタン -->
        <button id="delayed_button" class="hidden">遅延ボタン</button>

        <!--  AJAXデータ取得(JSON風) -->
        <button id="ajax_button">AJAXデータを取得</button>
        <pre id="ajax_result" class="hidden"></pre>

        <!--  iFrame 内のフォーム -->
        <h2>iFrame 内のフォーム</h2>
        <iframe id="test_frame" srcdoc="
            <form id='iframe_form'>
                <label id='iframe_label'>メッセージ: <input type='text' id='iframe_message'></label>
                <button type='submit' id='iframe_submit'>送信</button>
            </form>
            <script>
                document.getElementById('iframe_form').addEventListener('submit', function(event) {
                    event.preventDefault();
                    let message = document.getElementById('iframe_message').value.trim();
                    let parentDocument = window.parent.document;
                    let outputElement = parentDocument.getElementById('iframe_output');
                    if (message) {
                        outputElement.textContent = `送信されたメッセージ: ${message}`;
                    } else {
                        outputElement.textContent = '⚠️ メッセージを入力してください!';
                    }
                });
            </script>
        "></iframe>
        <p id="iframe_output" style="margin-top: 10px; font-weight: bold;"></p>

        <!-- Shadow DOM -->
        <h2>Shadow DOM</h2>
        <div class="shadow-container"></div>
        <p id="shadow_output" style="margin-top: 10px; font-weight: bold;"></p>

        <!-- ページスクロール -->
        <h2 class="long-page">スクロールして一番下へ</h2>
        <button id="scroll_button">ここをクリック</button>

        <!-- 新しいタブを開く -->
        <button id="new_tab">新しいタブを開く</button>

        <!-- ファイルアップロード -->
        <h2>ファイルアップロード</h2>
        <input type="file" id="file_upload">

        <!-- ドラッグ&ドロップ -->
        <h2>ドラッグ&ドロップ</h2>
        <div class="drop-zone" id="drop_zone">ここにドラッグ&ドロップ</div>

        <!-- aを使用した要素-->
        <br><br>
        <a href="https://www.google.com">Googleに移動</a>
        <br><br>

        <input id="test_input" type="text" placeholder="テスト入力">
        <button id="test_button" disabled>無効なボタン</button>
    </div>

    <script>
        // ✅ 新しいユーザーを追加
        let userIdCounter = 3;
        document.getElementById("add_user").addEventListener("click", function() {
            let name = document.getElementById("name").value.trim();
            let gender = document.querySelector('input[name="gender"]:checked');
            let country = document.getElementById("country").value;
            let agree = document.getElementById("agree").checked;
            
            if (!agree) {
                alert("⚠️ 規約に同意する必要があります!");
                return;
            }
            
            if (!name || !gender) {
                alert("⚠️ 名前と性別を入力してください!");
                return;
            }
            
            let table = document.getElementById("user_table");
            let newRow = table.insertRow();
            newRow.insertCell(0).textContent = userIdCounter++;
            newRow.insertCell(1).textContent = name;
            newRow.insertCell(2).textContent = gender.value === "male" ? "男性" : "女性";
            newRow.insertCell(3).textContent = country === "jp" ? "日本" : country === "us" ? "アメリカ" : "イギリス";
            let deleteCell = newRow.insertCell(4);
            let deleteBtn = document.createElement("button");
            deleteBtn.textContent = "削除";
            deleteBtn.classList.add("delete_btn");
            deleteBtn.addEventListener("click", function() {
                table.deleteRow(newRow.rowIndex - 1);
            });
            deleteCell.appendChild(deleteBtn);
        });

        // ✅ アラートボタン
        document.getElementById("alert_button").addEventListener("click", function() {
            alert("これはアラートメッセージです!");
        });

        // ✅ AJAXデータ取得(JSON風)
        document.getElementById("ajax_button").addEventListener("click", function() {
            setTimeout(() => {
                document.getElementById("ajax_result").classList.remove("hidden");

                // ✅ 現在の日時を取得
                let now = new Date();
                let formattedDate = `${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日 ${now.getHours()}時${now.getMinutes()}分${now.getSeconds()}秒`;

                // ✅ 表示内容を更新
                document.getElementById("ajax_result").textContent = JSON.stringify(
                    { message: "データ取得成功", timestamp: formattedDate },
                    null, 2
                );
            }, 2000);
        });

        // ✅ 掲示板の投稿を動的に追加
        document.getElementById("add_post").addEventListener("click", function() {
            let postList = document.getElementById("post_list");
            let newPost = document.createElement("li");
            newPost.textContent = "新しい投稿 " + (postList.children.length + 1);
            postList.appendChild(newPost);
        });

        // ✅ Shadow DOMの追加
        let shadowContainer = document.querySelector(".shadow-container");
        let shadowRoot = shadowContainer.attachShadow({mode: 'open'});
        let shadowButton = document.createElement("button");
        shadowButton.textContent = "Shadow DOMのボタン";
        shadowButton.id = "shadow_button";
        shadowRoot.appendChild(shadowButton);
        
        // Shadow DOM 内のボタンのクリックイベント
        shadowButton.addEventListener("click", function() {
            let outputElement = document.getElementById("shadow_output");
            outputElement.textContent = "✅ Shadow DOM のボタンが押されました!";
        });

        // ✅ 10秒後に遅延ボタンを表示
        setTimeout(() => {
            document.getElementById("delayed_button").classList.remove("hidden");
        }, 10000);

        // ✅ 遅延ボタン
        document.getElementById("delayed_button").addEventListener("click", function() {
            alert("✅ 遅延ボタンが押されました!");
        });

        // ✅ 一番下までスクロールする
        document.getElementById("scroll_button").addEventListener("click", function() {
            window.scrollTo({
            top: document.body.scrollHeight, // ページの最下部に移動
            behavior: "smooth" // スムーズスクロール
            });
        });

        // ✅ 新しいタブを開く
        document.getElementById("new_tab").addEventListener("click", function() {
            window.open("https://www.google.com", "_blank");
        });

        // ✅ ドロップ&ドラッグ
        document.addEventListener("DOMContentLoaded", function() {
        let dropZone = document.getElementById("drop_zone");

        // ドラッグしている間、スタイルを変更
        dropZone.addEventListener("dragover", function(event) {
            event.preventDefault(); // デフォルトの動作を防ぐ
            dropZone.style.backgroundColor = "#e0e0e0"; // 背景色を変更
        });

        // ドラッグがエリア外に出たら元のスタイルに戻す
        dropZone.addEventListener("dragleave", function() {
            dropZone.style.backgroundColor = "";
        });

        // ファイルがドロップされたときの処理
        dropZone.addEventListener("drop", function(event) {
            event.preventDefault(); // デフォルトの動作を防ぐ
            dropZone.style.backgroundColor = ""; // 背景色を元に戻す

            // ドロップされたファイルのリストを取得
            let files = event.dataTransfer.files;
            if (files.length > 0) {
                dropZone.textContent = `✅ ${files[0].name} がドロップされました!`;
            } else {
                dropZone.textContent = "⚠️ ファイルをドロップしてください!";
            }
        });
    });
    </script>
</body>
</html>

メモ帳などのエディタに上記の内容をコピーします。そして、名前を付けて保存で拡張子をhtmlにして保存します(たとえば、sample.htmlなど)。そのファイルをクリックしてブラウザで開くと、次のようなページが表示されます。いろいろな機能を試せるように、基本的な要素(テキスト、チェックボックスなど)の他に、Javascriptを使用してボタンやアラート、AJAX、iFrame、Shadow DOM、スクロールなどの要素を入れています。

ブラウザを開く方法

Seleniumでは、対応するWebDriverを使ってブラウザを開きます。ここでは、各ブラウザを開いて数秒待機した後に、ブラウザを閉じるコードを示します。ブラウザを開くにはgetメソッドを使用します。

状況getメソッドの引数
ローカルファイルを開くfile://HTMLファイルの絶対パス
(絶対パスはos.path.abspathを使用するとOSによらず同じコードを使用できる)
インターネット上のホームページを開くホームページのアドレス
(例えば、googleの場合はhttps://google.comを設定)

ブラウザを開く方法には、GUIを立ち上げる通常モードとGUIを立ち上げずにバックグラウンドで起動するヘッドレスモードがあります。

通常モード

Chrome(ChromeDriverManager)の場合は以下になります。

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

# Chromeのドライバを起動
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))
# 10秒間待つ
time.sleep(10)
# ブラウザを閉じる
driver.quit()

Firefox(GeckoDriver)の場合は以下になります。

from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
import os, time

# Firefoxのドライバを起動
driver = webdriver.Firefox(service=Service(GeckoDriverManager().install()))
# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))
# 10秒間待つ
time.sleep(10)
# ブラウザを閉じる
driver.quit()

Edge(EdgeChromiumDriverManager)の場合は以下になります。

from selenium import webdriver
from selenium.webdriver.edge.service import Service
from webdriver_manager.microsoft import EdgeChromiumDriverManager
import os, time

# Edgeのドライバを起動
driver = webdriver.Edge(service=Service(EdgeChromiumDriverManager().install()))
# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))
# 10秒間待つ
time.sleep(10)
# ブラウザを閉じる
driver.quit()

SafariをSeleniumで使う場合には、事前にWebDriverを有効化する必要があります。シェル上で次のコマンドを実行します。

safaridriver --enable

Pythonコードは以下となります。

from selenium import webdriver
import os, time

# Safariのドライバを起動
driver = webdriver.Safari()
# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))
# 10秒間待つ
time.sleep(10)
# ブラウザを閉じる
driver.quit()

これらのコードを実行すると、ブラウザが実際に開いて処理が行われます。

なお、ドライバは一度インストールするとキャッシュされるため、二回目以降はserviceオプションを削除しても動作します。インストール回数が多い場合はインストール回数の制限にかかる場合があるので、そのときは削除しましょう。

ヘッドレスモードで起動

ブラウザを開かずにバックグラウンドで操作する場合はヘッドレスモードを使います。ヘッドレスモードはSafariには公式では非対応です。

Chromeの場合を示します。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options  # 追加
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os

# Chromeオプションを設定
options = Options()
options.add_argument("--headless")  # ヘッドレスモードを有効化
options.add_argument(
    "--disable-gpu"
)  # 必要に応じてGPU無効化(Windows対策、Chromeのみ)

# Chromeのドライバを起動
driver = webdriver.Chrome(
    service=Service(ChromeDriverManager().install()), options=options
)

# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))

# ページのタイトルを取得
print(driver.title)

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

Firefoxの場合を示します。

from selenium import webdriver
from selenium.webdriver.firefox.options import Options  # 追加
from selenium.webdriver.firefox.service import Service
from webdriver_manager.firefox import GeckoDriverManager
import os

# Firefoxオプションを設定
options = Options()
options.add_argument("--headless")

# Firefoxのドライバを起動
driver = webdriver.Firefox(
    service=Service(GeckoDriverManager().install()), options=options
)

# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))

# ページのタイトルを取得
print(driver.title)

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

Edgeの場合を示します。

from selenium import webdriver
from selenium.webdriver.edge.options import Options  # 追加
from selenium.webdriver.edge.service import Service
from webdriver_manager.microsoft import EdgeChromiumDriverManager
import os

# Edgeオプションの設定
options = Options()
options.add_argument("--headless")

# Edgeのドライバを起動
driver = webdriver.Edge(
    service=Service(EdgeChromiumDriverManager().install()), options=options
)

# テスト用HTMLファイルを開く
driver.get("file://" + os.path.abspath("sample.html"))

# ページのタイトルを取得
print(driver.title)

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

Safariのヘッドレスモードは公式には非対応になっています。

なお、ドライバは一度インストールするとキャッシュされるため、二回目以降はserviceオプションを削除しても動作します。インストール回数が多い場合はインストール回数の制限にかかる場合がありますので、そのときは削除しましょう。

ヘッドレスモードでは画面が見えないので、スクリーンショットを撮って確認します。これを活用すると、ヘッドレスモードで動作中のページの状態を確認できます。

driver.save_screenshot("screenshot.png")

オプションの設定

add_argumentで設定するオプションには次のものがあります。必要に応じて設定しましょう。

オプション説明プラウザ
--headlessヘッドレスモードを有効化(GUIなし)Chrome/Firefox/Edge
--window-size=1920,1080ウィンドウサイズを指定Chrome/Edge/Safari
--width=1920
--height=1080
ウィンドウサイズを指定Firefox
--incognito / -private / --inprivateシークレットモード(プライベートブラウジング)--incognito(Chrome)
-private (Firefox/Safari)
--inprivate (Edge)
--disable-extensions拡張機能を無効化Chrome/Firefox/Edge
--ignore-certificate-errorsSSL証明書エラーを無視Chrome/Firefox/Edge/Safari
--disable-gpuWindowsの描画エラーを防ぐChrome/Edge
--start-maximizedブラウザを起動時に最大化Chrome/Edge
--user-agent="…"カスタムUser-Agentを設定Chrome/Firefox/Edge/Safari
--disable-dev-shm-usageディスクのメモリスペースを使う。Linuxで/dev/shmの制限を回避するために、代わりに/tmpを使う。Chrome
--mute-audioオーディオをミュートChrome/Edge
--no-sandboxChromeの保護機能を無効(Linuxでのクラッシュ回避)Chrome

要素を探索する方法

ブラウザを開いた後は、操作を行う要素を決めます。Seleniumで要素を探索して取得する方法として、find_elementfind_elementsがあります。

メソッド戻り値取得対象要素が見つからない場合
find_element(By,XXX, "値")単一の要素(WebElement最初に見つかった1つの要素のみエラー(NoSuchElementException)を発生
find_elements(By.XXX, "値")リスト(list[WebElement]該当するすべての要素を取得空のリスト([])を返す

By.XXXはWebページの要素を検索するためのロケータ(検索方法)を指定するものです。ロケータを使用するために、次のクラスをインポートします。

from selenium.webdriver.common.by import By

要素を指定する際には、要素の種類や属性の有無に応じてロケータを選択することになりますが、画面構成が変更されたときに修正ができるだけ発生しないロケータを選ぶようにします。SeleniumのByクラスには、以下のような検索方法が用意されています。

ロケータ説明使用例
By.IDid属性の値による指定find_element(By.ID, "search-box")
By.NAMEname属性の値による指定find_element(By.NAME, "username")
By.CLASS_NAMEクラス名による指定find_element(By.CLASS_NAME, "btn-primary")
By.TAG_NAMEHTMLタグ名による指定find_element(By.TAG_NAME, "h1")
By.LINK_TEXTa要素のテキストによる指定find_element(By.LINK_TEXT, "ログイン")
By.PARTIAL_LINK_TEXTa要素のテキストの部分一致による指定find_element(By.PARTIAL_LINK_TEXT, "登録")
By.CSS_SELECTORCSSセレクタ記法を使った指定find_element(By.CSS_SELECTOR, "div.container > p")
By.XPATHXPath記法を使った指定find_element(By.XPATH, "//input[@type='text']")

By.IDは一意の要素が取れるので最も安全な方法になります。また、複雑な検索やページ構造を考慮した検索を行う場合には、By.CSS_SELECTORBy.XPATHが役立ちます。find_elementで取得したWebElementに対し、さらにfind_elementfind_elementsメソッドを呼び出すと、最初に取得した要素の子孫要素から検索できます。

取得した要素の属性は、get_attiributeで確認できます。

引数には"id"や"class"、"href"、"value"などの属性名を指定します。HTMLファイルの探索された要素の中に記述された、指定した属性が返されます。

get_attribute("属性名")

get_attribute()で取得できる主な属性には以下のようなものがあります。

属性取得できる値
idID属性の値"search-box"
classクラス名"btn-primary large-button"
namename属性の値"username"
value<input><textarea> に入力された値"Selenium Python"
href<a> のリンク先"https://www.google.com"
src画像のURL"https://example.com/image.png"
checkedチェックボックスが選択されているか"true" または None
selectedセレクトボックスが選択されているか"true" または None
disabledボタンなどが無効かどうか"true" または None
placeholder入力欄のプレースホルダー"検索ワードを入力"
type入力タイプ"text" "password" "checkbox"

要素の探索とその結果得られた要素の属性を取得するサンプルコードを示します(Chromeの場合)。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os

# Chromeを起動し、ローカルのHTMLファイルを開く
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # 実際のHTMLファイルのパスを指定

try:
    print("=== By.XXX を使って要素を検索 ===")

    # ✅ IDで要素を取得(名前入力欄)
    print("ID:", driver.find_element(By.ID, "name").get_attribute("id"))

    # ✅ NAMEで要素を取得(性別選択のラジオボタン)
    print("NAME:", driver.find_element(By.NAME, "gender").get_attribute("name"))

    # ✅ CLASS_NAMEで要素を取得(ページ全体のコンテナ)
    print(
        "CLASS_NAME:",
        driver.find_element(By.CLASS_NAME, "container").get_attribute("class"),
    )

    # ✅ TAG_NAMEで要素を取得(ページの見出し)
    print(
        "TAG_NAME:", driver.find_element(By.TAG_NAME, "h1").text
    )  # 見出しのテキストを取得

    # ✅ LINK_TEXTで要素を取得(Googleへのリンク)
    print(
        "LINK_TEXT:",
        driver.find_element(By.LINK_TEXT, "Googleに移動").get_attribute("href"),
    )

    # ✅ PARTIAL_LINK_TEXTで部分一致検索(Googleを含むリンク)
    print(
        "PARTIAL_LINK_TEXT:",
        driver.find_element(By.PARTIAL_LINK_TEXT, "Google").get_attribute("href"),
    )

    # ✅ CSS_SELECTORで要素を取得(名前入力欄)
    print(
        "CSS_SELECTOR:",
        driver.find_element(By.CSS_SELECTOR, "input#name").get_attribute("id"),
    )

    # ✅ XPATHで要素を取得(名前入力欄)
    print(
        "XPATH:",
        driver.find_element(By.XPATH, "//input[@id='name']").get_attribute("id"),
    )

    print("\n=== get_attribute() を使って要素の属性を取得 ===")

    # ✅ 入力フォームの値を取得
    input_element = driver.find_element(By.ID, "name")
    print("value:", input_element.get_attribute("value"))  # 初期値 "Anonymous"
    print("type:", input_element.get_attribute("type"))  # "text"(入力タイプ)

    # ✅ チェックボックスの状態を取得(チェックされているか)
    checkbox = driver.find_element(By.ID, "agree")
    print(
        "checked:", checkbox.get_attribute("checked")
    )  # チェックされていれば "true"、されていなければ None

    # ✅ リンクの `href` を取得(リンク先URL)
    link = driver.find_element(By.LINK_TEXT, "Googleに移動")
    print("href:", link.get_attribute("href"))  # "https://www.google.com"

    print("\n=== ドロップダウンの選択状態を確認 ===")

    # ✅ ドロップダウンメニューを取得(国選択)
    dropdown = Select(driver.find_element(By.ID, "country"))

    # ✅ 現在選択されている `option` を取得
    selected_option = dropdown.first_selected_option
    print("selected:", selected_option.text)  # 初期状態では "日本"

    # ✅ すべての選択肢の `selected` 状態を確認
    options = driver.find_elements(By.XPATH, "//select[@id='country']/option")
    for option in options:
        print(
            f"{option.text}: {option.get_attribute('selected')}"
        )  # 選択されているなら "true"

    print("\n=== その他の属性を確認 ===")

    # ✅ 無効化されたボタンの `disabled` を取得(ボタンが使えないか確認)
    print(
        "disabled:", driver.find_element(By.ID, "test_button").get_attribute("disabled")
    )  # "true"

    # ✅ 入力フォームの `placeholder` を取得(ヒントテキスト)
    print(
        "placeholder:",
        driver.find_element(By.ID, "test_input").get_attribute("placeholder"),
    )  # "テスト入力"

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

実行すると、次の結果が得られます。

=== By.XXX を使って要素を検索 ===
ID: name
NAME: gender
CLASS_NAME: container
TAG_NAME: Seleniumテストページ
LINK_TEXT: https://www.google.com/
PARTIAL_LINK_TEXT: https://www.google.com/
CSS_SELECTOR: name
XPATH: name

=== get_attribute() を使って要素の属性を取得 ===
value: Anonymous
type: text
checked: None
href: https://www.google.com/

=== ドロップダウンの選択状態を確認 ===
selected: 日本
日本: true
アメリカ: None
イギリス: None

=== その他の属性を確認 ===
disabled: true
placeholder: テスト入力

要素を操作する方法

要素を探索した後は、その要素に対して操作を行います。

操作内容メソッド説明
クリックするWebElement.click()ボタンやリンクをクリック
テキストを入力するWebElement.send_keys("入力内容")入力フィールドにテキストを入力
テキストをクリアするWebElement.clear()入力フィールドのテキストを削除
フォームを送信するWebElement.submit()フォームを送信(<form>内の要素で有効)
ドロップダウンを選択する(値で選択)Select(WebElement).select_by_value("値")<select><option>valueの値から選択する
ドロップダウンを選択する(表示テキストで選択)Select(WebElement).select_by_visible_text("表示テキスト")<select><option>の表示テキストで選択する
ドロップダウンを選択する(インデックスで選択)Select(WebElement).select_by_index(1)<select><option>の順番で選択(0から開始)
キーボード操作WebElement.send_keys(Key.XXXX)キーボード操作をシミュレーション

クリック操作

クリックできる要素としてボタン、チェックボックス、ラジオボタン、リンクなどがあります。clickの使用例を示します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

# ボタンのクリック
driver.find_element(By.ID, "alert_button").click()  # アラートボタンをクリック
time.sleep(3)
driver.switch_to.alert.accept()  # アラートを閉じる

# チェックボックスのクリック
checkbox = driver.find_element(By.ID, "agree")
checkbox.click()  # チェックを入れる
print("チェック状態:", checkbox.get_attribute("checked"))  # "true" or None
time.sleep(3)

# ラジオボタンのクリック(男性を選択)
driver.find_element(By.XPATH, "//input[@name='gender'][@value='male']").click()
time.sleep(3)

# リンクをクリック
driver.find_element(By.LINK_TEXT, "Googleに移動").click()
time.sleep(3)

driver.quit()

テキストの入力とクリア

次に、テキストボックスとファイルアップロード(実際にインターネット上にアップロードするわけではありません)を例として、send_keys()clear()の使用例を示します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

# テキストボックスに入力
text_box = driver.find_element(By.ID, "name")
text_box.clear()
text_box.send_keys("テストユーザー")
print("入力された値:", text_box.get_attribute("value"))  # "テストユーザー"
time.sleep(3)

# ファイルアップロード
file_input = driver.find_element(By.ID, "file_upload")
file_input.send_keys(os.path.abspath("sample.html"))  # ファイルをアップロード

# 一番したまでスクロール(ファイルアップロードの確認)
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(3)

driver.quit()

リストの選択

ドロップダウンリストの選択を行う方法として、select_by_value, select_by_visible_text(), select_by_index()の使用例を示します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import Select
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

dropdown = Select(driver.find_element(By.ID, "country"))

# `select_by_value()`
dropdown.select_by_value("us")  # "アメリカ" を選択
print("選択された国:", dropdown.first_selected_option.text)  # "アメリカ"

# `select_by_visible_text()`
dropdown.select_by_visible_text("イギリス")  # "イギリス" を選択
print("選択された国:", dropdown.first_selected_option.text)  # "イギリス"

# `select_by_index()`
dropdown.select_by_index(0)  # インデックス0(日本)を選択
print("選択された国:", dropdown.first_selected_option.text)  # "日本"

driver.quit()

キーボード操作

Seleniumでは、キーボード操作もシミュレーションできます。テキストを入力する場合と同様にsend_keys()を使用します。

引数で指定できるキーの一覧を以下に示します。

操作内容Keys備考
Enterキーを押すKeys.ENTER検索ボックスやフォームの送信など
テキストの選択Keys.CONTROL, "a"全選択のショートカットキー(CTRL+a
コピーKeys.CONTROL, "c"コピーのショートカットキー(CTRL+c
ペーストKeys.CONTROL, "v"貼り付けのショートカットキー(CTRL+v
カットKeys.CONTROL, "x"切り取りのショートカットキー(CTRL+x
バックスペース(1文字削除)Keys.BACKSPACEカーソルの直前の文字を削除
デリート(1文字削除)Keys.DELETEカーソルの直後の文字を削除
矢印キー(移動)Keys.ARROW_LEFT
Keys.ARROW_RIGHT
左・右にカーソルを移動
Shift + 矢印キー(範囲選択)Keys.SHIFT, Keys.ARROW_LEFTカーソル移動しながら選択
タブで次の要素へ移動Keys.TABTABジャンプ
Escキーを押すKeys.ESCAPEダイアログを閉じる場合など

使用例を以下に示します。テストページの名前入力欄をつかって、いろいろなキー操作を試しています。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

# テキスト入力欄を取得
input_box = driver.find_element(By.ID, "name")
input_box.clear()

# `send_keys(Keys.XXXX)` を実行
input_box.send_keys("Selenium Test")  # 文字を入力
time.sleep(1)

input_box.send_keys(Keys.BACKSPACE)  # "t" を削除
time.sleep(1)

input_box.send_keys(Keys.CONTROL, "a")  # Ctrl + A(全選択)
time.sleep(1)

input_box.send_keys(Keys.CONTROL, "c")  # Ctrl + C(コピー)
input_box.clear()
time.sleep(1)

input_box.send_keys(Keys.CONTROL, "v")  # Ctrl + V(貼り付け)
time.sleep(1)

input_box.send_keys(Keys.ARROW_LEFT * 5)  # ←キーを5回押す(カーソルを左に移動)
time.sleep(1)

input_box.send_keys(Keys.SHIFT, Keys.ARROW_LEFT * 3)  # Shift + ←キー3回(範囲選択)
time.sleep(1)

input_box.send_keys(Keys.DELETE)  # Deleteキー(選択した部分を削除)
time.sleep(1)

input_box.send_keys(Keys.ENTER)  # Enterキーを押す(送信をシミュレーション)
time.sleep(1)

driver.quit()

待機処理

Seleniumでのテストや自動化では、ウェブページの要素がすぐ利用できるとは限らないため、適切な待機処理が必要となります。待機処理を入れずに要素を操作しようとすると、以下のようなエラーや不安定な動作が発生する可能性があります。

エラーの種類発生する状況
NoSuchElementExceptionページの読み込みが遅く、要素がまだ生成されていない
ElementNotVisibleException要素がページにあるが、まだ表示されていない
StaleElementReferenceException要素が動的に更新され、参照が切れてしまった
TimeoutException指定した時間内に要素が見つからない

待機処理にはtime.sleep()がありますが、SeleniumにはWebDriverWaitというメソッドが用意されています。これらには次の違いがあります。

方法メリットデメリット
time.sleep (固定時間待機)実装が簡単ページの速度に関係なく決まった時間待つため、不要な時間がかかる
WebDriverWait(条件付き待機)必要な時間だけ待機コードが少し複雑になる。

使い方は、次のようになります。

from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

# ドライバーを最大time秒まで待機
wait = WebDriverWait(driver, time)  

# By.XXXXで値を検索して得られる要素を、EC.XXXXで指定された条件を満たすまで待機させる
result = wait.until(EC.XXXX((By.XXXX, "値"))) 

待機させる要素の選択は、find_elementを使用する場合と同じです。待機を解消する条件の設定には、expected_conditions(通称、EC)のメソッドを使用します。

メソッド説明
presence_of_element_located((By.XXX, "値"))要素がページ上に存在していれば、要素WebElementを取得する(非表示でも可)
visibility_of_element_located((By.XXX, "値"))要素が表示されている(display: none;ではない)のであれば、要素WebElementを取得する
text_to_be_present_in_element((By.XXX, "値"), "テキスト")要素のテキストが特定の値になるのを待ち、条件を満たしたらTrueを返す。
alert_is_present()JavaScriptのアラート(alert(),confirm(), prompt())が表示されるのを待ち、条件を満たしたらAlertオプジェクトを返す。
frame_to_be_available_and_switch_to_it((By.XXX, "値"))iframeがロードされるのを待ち、条件を満たしたらswitch_to.frame()を実行し、成功すればTrueを返す。
staleness_of(WebElement)要素が無効になるのを待ち、Trueを返す。
(無効にならなければFalseを返す)

使用例を以下に示します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

wait = WebDriverWait(driver, 10)  # 最大で10秒待つ

### ✅ presence_of_element_located() ###

# 遅延ボタンが「DOM に存在する」ことを確認
element = wait.until(EC.presence_of_element_located((By.ID, "delayed_button")))
print("presence_of_element_located: 要素が存在する")

### ✅ visibility_of_element_located() ###

# 遅延ボタンが表示されるのを待つ(display: none; ではない)
element = wait.until(EC.visibility_of_element_located((By.ID, "delayed_button")))
print("visibility_of_element_located: 要素が表示された")

### ✅ text_to_be_present_in_element() ###

# AJAXボタンをクリック
driver.find_element(By.ID, "ajax_button").click()

# AJAXの結果が「データ取得成功」になるのを待つ
result = wait.until(
    EC.text_to_be_present_in_element((By.ID, "ajax_result"), "データ取得成功")
)
print("text_to_be_present_in_element: AJAXのデータが表示された")

time.sleep(4)  # 画面確認

### ✅ alert_is_present() ###

# アラートボタンをクリック
driver.find_element(By.ID, "alert_button").click()

# アラートが表示されるのを待つ
alert = wait.until(EC.alert_is_present())
print("alert_is_present: アラートが表示された")

time.sleep(4)  # 画面確認

# アラートを閉じる
alert.accept()

### ✅ frame_to_be_available_and_switch_to_it() ###

# iframe が利用可能になるのを待つ
wait.until(EC.frame_to_be_available_and_switch_to_it((By.ID, "test_frame")))
print("frame_to_be_available_and_switch_to_it: iframe に切り替え成功")

# iframe 内の入力フィールドに文字を入力
iframe_input = driver.find_element(By.ID, "iframe_message")
iframe_input.send_keys("iframe内のテスト")

# iframeの外に戻る
driver.switch_to.default_content()

time.sleep(4)  # 画面確認

### ✅ staleness_of() ###

# ボタンを取得
button = driver.find_element(By.ID, "add_user")

# ページをリロード(以前の要素は `stale` になる)
driver.refresh()

# 利用規約にチェックをつけて、性別で女性を選択
driver.find_element(By.ID, "agree").click()
driver.find_element(By.XPATH, "//input[@type='radio' and @value='female']").click()

# 要素が無効化されるのを待つ
result = wait.until(EC.staleness_of(button))
print("staleness_of: 要素が無効化された")
if result:
    button = wait.until(EC.presence_of_element_located((By.ID, "add_user")))
    button.click()

time.sleep(4)  # 画面確認

driver.quit()

ページ遷移

ページの遷移のメソッドとして代表的なものに以下があります。

メソッド説明
back()戻る
forward()進む
switch_to.window()タブの移動
refresh()リロード

使用例を示します。サンプルのHTMLファイルとgoogleの検索サイトを用いてページの遷移を行っています。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

### ✅ back()とforward() ###

# 「Googleに移動」のリンクをクリック(新しいページに遷移)
driver.find_element(By.LINK_TEXT, "Googleに移動").click()
time.sleep(2)  # 少し待機

# 戻る
driver.back()
time.sleep(2)  # 少し待機
print("戻る: 元のページに戻りました")

# 進む
driver.forward()
time.sleep(2)  # 少し待機
print("進む: 次のページに進みました")

# 戻る
driver.back()
time.sleep(2)  # 少し待機
print("戻る: 元のページに戻りました")

### ✅ switch_to.window() ###

# 「新しいタブを開く」ボタンをクリック
driver.find_element(By.ID, "new_tab").click()
time.sleep(2)

# すべてのタブを取得
tabs = driver.window_handles
print("現在開いているタブ:", tabs)

# 新しいタブに切り替え
driver.switch_to.window(tabs[1])
time.sleep(2)  # 少し待機
print("新しいタブに切り替えました")

# 元のタブに戻る
driver.switch_to.window(tabs[0])
time.sleep(2)  # 少し待機
print("元のタブに戻りました")

driver.quit()

HTMLの取得

現在のページのHTMLの取得にはdriver.page_sourceを使用します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

html_source = driver.page_source
print(html_source)  # ページのHTMLが表示される

driver.quit()

インラインフレームとShadow DOMの操作

通常の要素操作とはことなり、インラインフレーム(iframe)とShadow DOMSeleniumで操作するには特別な処理が必要になります。

項目方法
iframe
(インラインフレーム)
ページが分割されているため、switch_to.frame()iframeの内側に切り替えてから操作する。iframeの外側に戻る場合にはswitch_to.default_content()を用いる。
Shadow DOM
(シャドウ DOM)
通常はfind_element()ではアクセスできず、shadow_rootを取得する必要がある。

使用例を示します。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import os, time

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get("file://" + os.path.abspath("sample.html"))  # ローカルHTMLのパスを指定

### ✅ iframe ###

# `iframe` に切り替え
driver.switch_to.frame("test_frame")  # `id="test_frame"` の `iframe` に切り替え
print("iframe に切り替え成功!")

# `iframe` 内の要素を操作(例: input に文字を入力)
iframe_input = driver.find_element(By.ID, "iframe_message")
iframe_input.send_keys("iframe 内のテスト")

# `iframe` の外(元の HTML)に戻る
driver.switch_to.default_content()
print("元のページに戻りました!")

time.sleep(4)

### ✅ Shadow DOM ###

# Shadow DOM のルート要素を取得
shadow_host = driver.find_element(By.CSS_SELECTOR, ".shadow-container")
shadow_root = driver.execute_script("return arguments[0].shadowRoot", shadow_host)

# Shadow DOM 内のボタンを取得してクリック
shadow_button = shadow_root.find_element(By.ID, "shadow_button")
shadow_button.click()

print("Shadow DOM のボタンをクリックしました!")

time.sleep(4)
driver.quit()

まとめ

本記事では、Python の Selenium を使ったブラウザ自動操作の基本を解説しました。特に、以下のポイントについて詳しく説明しました。

  • 基本操作(要素の検索、クリック、入力)
  • ページ遷移(戻る・進む・タブ移動・リロード)
  • 特殊な要素の操作(iframe・Shadow DOM)
  • 待機処理(要素の表示を待つ)

Selenium を活用すれば、テストの自動化だけでなく、Web スクレイピングや業務効率化にも役立ちます。ぜひ、実際にコードを動かしながら、試してみてください!

-TECHNOLOGY
-