Seleniumライブラリ

スクレイピング

Seleniumは、元々ウェブアプリケーションの自動テストのために開発されたツールスイートですが、Pythonライブラリと組み合わせることで、Webブラウザを自動操作する強力なツールとして、ウェブスクレイピング、Webアプリケーションの自動化、RPA(Robotic Process Automation)など、幅広い分野で活用されています。

Seleniumライブラリ

特に、JavaScriptによって動的にコンテンツが生成されるようなモダンなWebサイト(SPA: Single Page Applicationなど)のスクレイピングにおいては、HTMLソースを直接解析するRequestsBeautifulSoupだけでは対応できないことが多く、実際にブラウザを起動してページをレンダリングするSeleniumが非常に有効な手段となります。

1. Seleniumのインストールとセットアップ

Seleniumを使用するためには、以下の2つの要素が必要です。

  1. Selenium Pythonパッケージ: pipでインストールします。

    Bash

    pip install selenium
    
  2. WebDriver: Seleniumがブラウザを制御するためのインターフェースです。操作したいブラウザの種類(Chrome, Firefox, Edgeなど)に対応するWebDriverをダウンロードし、Pythonスクリプトからアクセスできるようにパスを通す必要があります。

ダウンロードしたWebDriverの実行ファイル(例: chromedriver.exe)は、以下のいずれかの方法でPythonスクリプトからアクセス可能にします。

  • システム環境変数 PATH にWebDriverのパスを追加する。
  • WebDriverの実行ファイルをPythonスクリプトと同じディレクトリに置く。
  • コード内でWebDriverのパスを明示的に指定する。

    Python

    from selenium import webdriver
    from selenium.webdriver.chrome.service import Service
    
    # 例: ChromeDriverのパスを直接指定する場合
    # service = Service(executable_path='/path/to/chromedriver') # macOS/Linux
    service = Service(executable_path='C:\\path\\to\\chromedriver.exe') # Windows
    driver = webdriver.Chrome(service=service)
    

2. WebDriverの起動と基本操作

WebDriverを起動すると、指定したブラウザのウィンドウが自動的に開かれます。

Python

from selenium import webdriver
import time

# WebDriverを起動(今回はパスが通っている前提)
driver = webdriver.Chrome() 
# driver = webdriver.Firefox() # Firefoxの場合

try:
    # 目的のURLにアクセス
    driver.get("https://www.google.com")
    print(f"現在のページのタイトル: {driver.title}")

    # ページが完全に読み込まれるまで待つ(明示的な待機)
    time.sleep(3) 

    # ページソースを取得
    # print(driver.page_source[:500]) # 最初の500文字

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

except Exception as e:
    print(f"エラーが発生しました: {e}")
    driver.quit()

3. 要素の検索 (find_element_by_*, find_elements_by_*)

Seleniumの主要な機能は、Webページ上の要素(ボタン、入力フィールド、リンクなど)を特定し、操作することです。要素の検索には様々な方法があります。

3-1. 単一要素の検索 (find_element)

最初に見つかった要素を WebElement オブジェクトとして返します。見つからない場合は NoSuchElementException を発生させます。

  • driver.find_element(By.ID, "element_id"): id 属性で検索
  • driver.find_element(By.NAME, "element_name"): name 属性で検索
  • driver.find_element(By.CLASS_NAME, "element_class"): class 属性で検索
  • driver.find_element(By.TAG_NAME, "a"): タグ名で検索
  • driver.find_element(By.LINK_TEXT, "完全一致のリンクテキスト"): リンクの表示テキストが完全に一致するものを検索
  • driver.find_element(By.PARTIAL_LINK_TEXT, "部分一致のリンクテキスト"): リンクの表示テキストが部分的に一致するものを検索
  • driver.find_element(By.CSS_SELECTOR, "div.my-class > a"): CSSセレクタで検索
  • driver.find_element(By.XPATH, "//div[@id='my_id']/p"): XPathで検索

Byクラスの使用: Selenium 4からは、Byクラスを使って検索方法を明示的に指定するのが推奨されています。

Python

from selenium.webdriver.common.by import By

# Googleの検索ボックスを名前属性で検索
search_box = driver.find_element(By.NAME, "q")
search_box.send_keys("Selenium Python") # テキストを入力
search_box.submit() # フォームを送信

3-2. 複数要素の検索 (find_elements)

条件に合致するすべての要素を WebElement オブジェクトのリストとして返します。見つからない場合は空のリストを返します。

Python

# すべてのリンク要素を取得
all_links = driver.find_elements(By.TAG_NAME, "a")
for link in all_links:
    print(link.text, link.get_attribute('href'))

# 特定のクラスを持つすべての要素を取得
elements = driver.find_elements(By.CLASS_NAME, "some-class")

4. WebElementオブジェクトの操作

find_elementなどで取得した WebElement オブジェクトには、以下のような操作が可能です。

  • element.click(): 要素をクリック
  • element.send_keys("テキスト"): テキスト入力フィールドにテキストを入力
  • element.clear(): テキスト入力フィールドの内容をクリア
  • element.submit(): 親フォームを送信
  • element.text: 要素の表示テキストを取得
  • element.get_attribute("属性名"): 指定した属性の値を取得(例: href, src, value
  • element.is_displayed(): 要素が表示されているか(True/False
  • element.is_enabled(): 要素が有効か(True/False
  • element.is_selected(): チェックボックスやラジオボタンが選択されているか(True/False

5. 待機処理(Waits)

動的にコンテンツが読み込まれるWebページでは、要素がまだ存在しないうちに検索しようとしてエラーになることがあります。これを避けるために、要素が出現するまで待機する処理が必要です。

5-1. 暗黙的な待機 (Implicit Waits)

特定の時間内であれば、要素が見つかるまでWebDriverがDOMをポーリング(監視)し続けます。一度設定すると、そのWebDriverインスタンスのライフサイクル全体に適用されます。

Python

driver.implicitly_wait(10) # 10秒間、要素が見つかるまで待機
# これ以降のfind_element/sは、最大10秒待機するようになる

5-2. 明示的な待機 (Explicit Waits)

特定の条件が満たされるまで、WebDriverが最大指定時間まで待機します。より柔軟で、ピンポイントな待機が可能です。

Python

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

try:
    # 最大10秒待機し、IDが'myButton'の要素がクリック可能になるまで待つ
    button = WebDriverWait(driver, 10).until(
        EC.element_to_be_clickable((By.ID, "myButton"))
    )
    button.click()

    # 最大5秒待機し、classが'loading'の要素がDOMから消えるまで待つ
    WebDriverWait(driver, 5).until_not(
        EC.presence_of_element_located((By.CLASS_NAME, "loading"))
    )

except Exception as e:
    print(f"要素が見つからないか、クリックできませんでした: {e}")

expected_conditionsには他にも多くの便利な条件が用意されています。

6. Headlessモードとオプション設定

ブラウザのGUIを開かずにバックグラウンドで動作させる「Headlessモード」は、サーバー環境での実行や、GUIの表示が不要な場合に非常に便利です。

Python

from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--headless") # Headlessモードを有効化
chrome_options.add_argument("--no-sandbox") # Docker環境などで必要
chrome_options.add_argument("--disable-dev-shm-usage") # Docker環境などで必要
chrome_options.add_argument("--window-size=1920,1080") # 仮想ウィンドウサイズ設定

driver = webdriver.Chrome(options=chrome_options)

他にも、様々なオプションを設定することで、WebDriverの挙動をカスタマイズできます。

  • add_argument("--incognito"): シークレットモードで起動
  • add_argument("--disable-gpu"): GPUハードウェアアクセラレーションを無効化
  • add_argument("user-agent=..."): User-Agentを偽装

7. その他の高度な機能

  • JavaScriptの実行: driver.execute_script("alert('Hello');") で任意のJavaScriptコードを実行できます。動的なコンテンツ操作やスクロールなどに利用します。
  • フレーム/ウィンドウの切り替え: 複数のフレームやウィンドウを扱う場合、driver.switch_to.frame()driver.switch_to.window() で対象を切り替えます。
  • スクリーンショット: driver.save_screenshot("screenshot.png") でページのスクリーンショットを保存できます。デバッグや記録に役立ちます。
  • アラート(JavaScriptのポップアップ)の処理: driver.switch_to.alert.accept()(OKを押す)や dismiss()(キャンセルを押す)で処理します。
  • クッキーの操作: driver.get_cookies(), driver.add_cookie(), driver.delete_cookie() などでクッキーを管理できます。

8. Seleniumとスクレイピングの注意点と倫理

Seleniumは非常に強力ですが、以下の点を理解しておく必要があります。

  • 速度: 実際のブラウザを起動するため、Requestsなどと比べて処理速度は遅くなります。
  • リソース消費: CPUやメモリを多く消費します。同時に多数のブラウザを起動するとシステムに大きな負荷がかかります。
  • 検知されやすさ: 一部のサイトでは、Seleniumによる自動操作を検知し、アクセスをブロックする対策が取られていることがあります。
  • 倫理と法律: ウェブスクレイピングを行う際は、必ず対象サイトのrobots.txtを確認し、利用規約を遵守し、サーバーに過度な負荷をかけないように注意してください。法的な問題にも留意する必要があります。

まとめ

Seleniumは、Pythonと組み合わせることで、JavaScriptによって動的に生成されるコンテンツを含むWebサイトの操作やデータ収集を可能にする非常に強力なツールです。Webスクレイピングだけでなく、RPA、自動テスト、Webアプリケーションのデバッグなど、その応用範囲は多岐にわたります。

しかし、そのパワーと引き換えに、RequestsBeautifulSoup単体よりも多くのリソースを消費し、速度も低下するというトレードオフがあります。そのため、スクレイピングの対象サイトの特性(静的か動的か、JavaScriptの多用度など)に応じて、最適なライブラリを選択することが重要です。

適切な待機処理、オプション設定、そして倫理的な配慮を組み合わせることで、SeleniumはPython開発者にとって非常に価値のある武器となるでしょう。