selenium wire proxy

Selenium Wire は、Python で認証付きプロキシを使ったブラウザ自動化を実現する手軽な方法です。login:password 形式のプロキシ URL を 1 つのオプションでそのまま指定できるため、素の Selenium で必要になる拡張機能による回避策は不要です。さらに、ブラウザが送受信するすべての HTTP リクエストとレスポンスを確認できるため、スクレイピングや QA のチームに選ばれています。

このガイドでは、ライブラリの安全なインストールとバージョン固定、認証付きプロキシの設定、出口 IP の確認、リクエストの検査と待機、ヘッダーの編集、IP のローテーション、ヘッドレス実行、メモリ使用量の削減、HTTPS 証明書の扱い、undetected-chromedriver との組み合わせ、そして最新の代替手段について解説します。

DataImpulse は、195 か国で 9,000 万を超える住宅用、モバイル、データセンター IP を提供する、倫理的調達を重視したプロキシプロバイダーです。料金は 1 GB あたり 1 ドルからの従量課金制で、トラフィックに有効期限はありません。Web スクレイピング、広告検証、価格モニタリング、市場調査、複数アカウントの管理に利用できます。

重要なポイント

  • Selenium Wire プロキシ: Selenium Wire では、login:password 形式のプロキシ URL を seleniumwire_options にそのまま指定できます。そのため、素の Selenium で必要になる拡張機能による回避策なしに、認証付きブラウザ自動化を実行できます。
  • 最適なプロキシの種類: ローテーティング住宅用プロキシ。実在の利用者に割り当てられた IP を使用できます。
  • 価格: 1 GB あたり 1 ドルから、従量課金で、トラフィックは失効せず、サブスクリプションもありません。
  • カバレッジ: 195 か国で利用できる、倫理的に調達された 9,000 万超の IP。
  • 信頼性: 成功率 99.51%、G2 で 5 点満点中 4.8 の評価。
  • プロトコルとターゲティング: HTTP、HTTPS、SOCKS5 に対応し、標準で国別ターゲティングを利用できます。
Selenium Wire をプロキシ経由でルーティングする

Selenium Wire とは? 今もメンテナンスされている?

Selenium Wire は Selenium を拡張する Python ライブラリです。ブラウザの HTTP リクエストとレスポンスを検査、待機、変更できるようにし、認証付きプロキシを標準でサポートします。ローカルで man-in-the-middle プロキシを起動し、ブラウザのトラフィックを実際の上流プロキシへ転送する仕組みです。

注意点として、元のプロジェクトはアーカイブ済みで、積極的なメンテナンスは行われていません。本番環境でも十分に動作しますが、バージョンを固定し、Selenium、Chrome、依存関係を更新する際はリリース前に隔離環境でテストしてください。互換性修正を引き継ぐコミュニティフォークもあります。後半の比較表では、長期運用では Playwright などメンテナンスが継続しているツールのほうが適するケースを示します。

それでもチームに選ばれる理由は、導入の手軽さです。既存の Selenium テストスイートやスクレイパーがあれば、import を 1 行変更してプロキシオプションを加えるだけで、認証付きプロキシのサポートと、ページ上のすべてのリクエストを確認する機能をすぐに利用できます。素の Selenium でこのリクエストレベルの可視性を作り直すには相応の作業が必要なため、既存のコードベースでは、アーカイブ済みであっても採用する価値がある場合が少なくありません。データ収集のために実ブラウザを操作するのが初めてなら、動的な Web ページのスクレイピング方法に関する当社ガイドで、レンダリングの全体像とブラウザが必要になる場面を確認してください。

Selenium Wire をインストールし、破損を防ぐためにバージョンを固定するには?

selenium とともに selenium-wire をインストールし、blinker は 1.8 未満に固定してください。blinker 1.8 で、Selenium Wire が起動時に import する内部名が削除されたためです。プロジェクトがアーカイブ済みである以上、依存関係のバージョンを固定しないことが、動作していた構成が突然壊れる最も一般的な原因です。

よくある問題は、blinker の自動アップグレード後に発生する WeakNamespace の ImportError です。次のようにバージョンを固定すれば回避できます。

# Selenium Wire is archived. Pin known-good versions so an upstream release
# does not break your build overnight.
#
# blinker >= 1.8 removed blinker._saferef / WeakNamespace, which Selenium Wire
# imports at startup. On blinker 1.8+ you get:
#   ImportError: cannot import name 'WeakNamespace' from 'blinker'
# The fix is to hold blinker below 1.8.
pip install "selenium-wire==5.1.0" "selenium==4.9.1" "blinker==1.7.0"

# Selenium Wire also depends on brotli and can trip on very new Selenium.
# If you must run current Selenium, test in a throwaway virtualenv first, or
# move to a maintained fork such as selenium-wire-2 that tracks these fixes.

継続的インテグレーションやチームメンバーが同じ検証済みの組み合わせを使えるよう、これらの固定は requirements ファイルに記載してください。新しい Selenium へ移行する場合は、pip に最新版を一括解決させるのではなく、独自のテストを伴う計画的なアップグレードとして進めましょう。

Selenium Wire で認証付きプロキシを設定するには?

ドライバーの作成時に seleniumwire_options でプロキシの辞書を渡し、ユーザー名とパスワードを URL に埋め込みます。localhost は no_proxy で除外してください。認証付きプロキシを容易に扱えることは、プロキシ利用で素の Selenium ではなく Selenium Wire を選ぶ大きな理由です。

webdriver は selenium ではなく seleniumwire から import し、オプションを渡します。認証情報、ホスト、ポートはプロバイダーのダッシュボードで確認できます。DataImpulse ではホストが gw.dataimpulse.com、ポートが 823 です。

from seleniumwire import webdriver  # import from seleniumwire, not selenium

proxy_url = "http://login:[email protected]:823"

seleniumwire_options = {
    "proxy": {
        "http": proxy_url,
        "https": proxy_url,
        "no_proxy": "localhost,127.0.0.1",
    }
}

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com")
print(driver.title)
driver.quit()

no_proxy の設定により、ローカルアドレスはプロキシを経由せず、ドライバーは ChromeDriver と直接通信できます。認証情報が誤っている場合は、通常 407 応答が返されます。407 Proxy Authentication Required エラーに関する当社のメモが、その診断方法を説明します。認証情報付きプロキシが一般にどう機能するかの背景については、住宅用プロキシをご覧ください。

プロキシの出口 IP が機能しているか確認するには?

ドライバーで api.ipify.org などの IP 応答エンドポイントを開き、返されたアドレスが自分のマシンではなくプロキシのものであることを確認します。単にページが読み込めたからといって、プロキシが有効だと判断してはいけません。

import json
from seleniumwire import webdriver

proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
    "proxy": {"http": proxy_url, "https": proxy_url,
              "no_proxy": "localhost,127.0.0.1"}
}

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://api.ipify.org/?format=json")

body = driver.find_element("tag name", "body").text
exit_ip = json.loads(body)["ip"]
print("Exit IP:", exit_ip)  # should be the proxy, not your own address

driver.quit()

応答に実際の IP が表示された場合は、次の 3 点を確認してください。no_proxy が誤ってターゲットに一致していないか、認証情報が正しいか、webdriver を seleniumwire から import しているかです。この確認は新しいジョブの開始時に必ず行い、プロキシ設定を変更した後にも再実行してください。

特定のリクエストを検査して待機するには?

driver.requests でブラウザが送受信したすべてのリクエストとレスポンスを確認し、driver.wait_for_request で条件に一致する呼び出しが現れるまで待機します。これは Selenium Wire と通常の WebDriver を分ける機能で、ページの背後で使われている JSON API を見つける際に特に役立ちます。

from seleniumwire import webdriver

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com/products")

# Block until a request whose URL matches the regex is captured.
request = driver.wait_for_request(r"/api/v2/products", timeout=15)
print(request.method, request.url)
print("Status:", request.response.status_code)
print("Type:", request.response.headers["Content-Type"])

# Walk every captured request/response pair the browser made.
for r in driver.requests:
    if r.response:
        print(r.response.status_code, r.url)

driver.quit()

wait_for_request は URL と照合する正規表現を受け取り、リクエストを捕捉するとすぐに返ります。そのため、不安定な固定時間の sleep を避けられます。どのバックグラウンド呼び出しがデータを取得しているかが分かれば、レンダリングを省いてそのエンドポイントへ直接リクエストできることが多く、コストも大幅に抑えられます。この手法はWeb スクレイピングのベストプラクティスの基本となる考え方です。

インターセプターでリクエストヘッダーを変更するには?

driver.request_interceptor に関数を割り当てると、各リクエストがブラウザを離れる前にその関数が実行されます。これにより、ヘッダーの上書き、トークンの追加、パラメーターの削除が可能です。実際の利用環境に沿った User-Agent や言語を設定する用途でよく使われます。

from seleniumwire import webdriver

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)

def interceptor(request):
    # Delete first, then set, so you replace the header instead of duplicating it.
    del request.headers["User-Agent"]
    request.headers["User-Agent"] = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
    request.headers["Accept-Language"] = "en-US,en;q=0.9"

driver.request_interceptor = interceptor
driver.get("https://httpbin.org/headers")
print(driver.find_element("tag name", "body").text)
driver.quit()

新しい値を設定する前に既存のヘッダーを削除してください。削除しないと、Selenium Wire が元の値と置き換えた値の両方を送信することがあります。対応する response_interceptor ではレスポンスの読み取りや書き換えもできます。インターセプターは画像やスクリプトを含むすべてのリクエストで実行されるため、処理は軽量に保ちましょう。一貫性のある自然なヘッダーは、Web スクレイピングのベストプラクティスの中でも目立たないシグナルの一つです。

Selenium Wire でリクエストごとにプロキシをローテーションするには?

方法は 2 つあります。実行時に driver.proxy を再代入して同じブラウザ内で設定を切り替える方法と、クリーンなプロファイルと cookie ジャーも必要な場合にドライバーを作り直す方法です。DataImpulse のようなローテーティングゲートウェイは、新しい接続ごとに新しい住宅用出口を払い出すため、ほとんどのジョブでは国を変えるときだけ設定を切り替えれば十分です。

from seleniumwire import webdriver

base = "http://login:[email protected]:823"
opts = {"proxy": {"http": base, "https": base,
                  "no_proxy": "localhost,127.0.0.1"}}
driver = webdriver.Chrome(seleniumwire_options=opts)

# Option A: reassign driver.proxy at runtime to switch config (for example a
# different country gateway) without rebuilding the browser. Cheap and fast.
uk = "http://login:[email protected]:823"
driver.proxy = {"http": uk, "https": uk, "no_proxy": "localhost,127.0.0.1"}
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()

# Option B: recreate the driver per job when you need a guaranteed clean
# browser profile and cookie jar as well as a fresh exit IP.
def fresh_driver():
    return webdriver.Chrome(seleniumwire_options=opts)

for _ in range(3):
    d = fresh_driver()
    d.get("https://api.ipify.org")
    print(d.find_element("tag name", "body").text)
    d.quit()

driver.proxy の再代入は低コストで、ブラウザを起動したまま使えるため、起動コストが大きい大量処理に向いています。ドライバーの作り直しは負荷が高い一方、ジョブ間の分離を保証でき、ターゲットがセッションを IP だけでなく cookie やローカルストレージにも結び付ける場合に有効です。クリーンな識別情報が必要か、それとも単に新しいアドレスが必要かで選んでください。実務上は、匿名の公開ページを収集する間はプロキシを再代入し、アカウントやログインの境界を越えるたびにドライバーを作り直すと、前の実行の cookie が次の実行に引き継がれません。モバイル利用者の識別を積極的に行うターゲットでは、難しいケースでモバイルプロキシが必要になることがある一方、負荷の軽いページにはより安価な出口を使えます。

Selenium Wire をヘッドレスで実行し、メモリ使用量を抑えるには?

ヘッドレスモードと安定動作のための Chrome オプションを追加し、Selenium Wire が捕捉する内容を制限してリクエストバッファが無制限に増えないようにします。サーバー上では、ヘッドレス実行と範囲を絞った捕捉が、長時間動作するジョブと RAM を使い果たすジョブを分けます。

まずは、ヘッドレスのコンテナや CI 環境で安定して動作する Chrome フラグから始めます。

from seleniumwire import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument("--headless=new")     # modern headless mode
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--window-size=1920,1080")

proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
    "proxy": {"http": proxy_url, "https": proxy_url,
              "no_proxy": "localhost,127.0.0.1"}
}

driver = webdriver.Chrome(options=chrome_options,
                          seleniumwire_options=seleniumwire_options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()

既定では、Selenium Wire はすべてのリクエストとレスポンスを捕捉してバッファに保持します。これが長時間の実行でメモリを消費する主な原因です。driver.scopes で捕捉対象を絞り、ストレージをメモリ内に保持し、ページ間でバッファをクリアしてください。

from seleniumwire import webdriver

seleniumwire_options = {
    "proxy": {"http": proxy_url, "https": proxy_url,
              "no_proxy": "localhost,127.0.0.1"},
    "request_storage": "memory",   # keep the buffer in RAM, not on disk
}

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)

# Only capture the API traffic you care about. Images, fonts, analytics, and
# tracking pixels are ignored, which keeps the capture buffer small.
driver.scopes = [r".*/api/.*"]

driver.get("https://example.com/products")
for request in driver.requests:
    print(request.url)

del driver.requests   # clear the buffer between pages on long-running jobs
driver.quit()

scopes リストには URL に一致させる正規表現を指定します。対象外のリクエストは通過しますが保存されません。API のレスポンスだけが必要なスクレイパーでは、常駐バッファを大幅に削減できます。ダウンロード量を抑えれば、ギガバイト単位で課金される DataImpulse のトラフィックコストも下がります。

Selenium Wire は HTTPS と証明書をどう扱うのか?

暗号化されたリクエストとレスポンスの本文を読むため、Selenium Wire は自身のルート証明書を使う man-in-the-middle として HTTPS を復号します。この証明書は Chrome と Firefox のブラウザプロファイルに自動で追加されます。便利な機能ですが、利用前に理解しておくべき制約があります。

from seleniumwire import webdriver

proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
    "proxy": {"http": proxy_url, "https": proxy_url,
              "no_proxy": "localhost,127.0.0.1"},
    # Selenium Wire is a man-in-the-middle proxy: to read HTTPS bodies it
    # decrypts traffic using its own root certificate, which it injects into
    # the browser profile automatically. These two options relax verification
    # on the upstream leg so a mismatched or self-signed cert does not abort.
    "verify_ssl": False,
    "suppress_connection_errors": True,
}

driver = webdriver.Chrome(seleniumwire_options=seleniumwire_options)
driver.get("https://example.com")
driver.quit()

この man-in-the-middle の設計には 2 つの注意点があります。第一に、certificate pinning を使うサイトは追加された証明書を拒否するため、そのトラフィックを傍受できません。その場合は該当ホストの捕捉を無効にするか、本文の検査を行わないでください。第二に、カスタムプロファイルや既定以外のプロファイルで Chrome を起動する場合は、そのプロファイルで Selenium Wire の CA が信頼されているか確認が必要になることがあります。verify_ssl と suppress_connection_errors は上流側の検証を緩和し、通常と異なる証明書で実行が中断しないようにしますが、certificate pinning を回避するものではありません。

undetected-chromedriver と組み合わせられる? 代替手段は?

はい。Selenium Wire には undetected-chromedriver との統合が含まれており、seleniumwire.undetected_chromedriver として import できます。これによりリクエストの検査と認証付きプロキシを利用でき、undetected-chromedriver は自動化のフィンガープリントを減らします。検出対策が厳しいターゲットでよく使われる組み合わせです。

# Selenium Wire ships its own undetected-chromedriver integration.
import seleniumwire.undetected_chromedriver as uc

proxy_url = "http://login:[email protected]:823"
seleniumwire_options = {
    "proxy": {"http": proxy_url, "https": proxy_url,
              "no_proxy": "localhost,127.0.0.1"}
}

options = uc.ChromeOptions()
options.add_argument("--headless=new")

driver = uc.Chrome(seleniumwire_options=seleniumwire_options, options=options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()

Selenium Wire 自体が適さない場合は、次の 2 つの代替手段でほとんどの要件を満たせます。素の Selenium 4 では、小さな拡張機能を生成して認証付きプロキシを利用でき、補助ライブラリがその作成を自動化します。

from selenium import webdriver
# Plain Selenium cannot send proxy credentials on its own. A small helper builds
# a throwaway Chrome extension that answers the proxy auth challenge for you.
from selenium_authenticated_proxy import SeleniumAuthenticatedProxy

proxy = SeleniumAuthenticatedProxy(
    proxy_url="http://login:[email protected]:823"
)
options = webdriver.ChromeOptions()
proxy.enrich_options(options)

driver = webdriver.Chrome(options=options)
driver.get("https://api.ipify.org")
print(driver.find_element("tag name", "body").text)
driver.quit()

Playwright は認証付きプロキシをネイティブに扱え、積極的にメンテナンスされているため、新規プロジェクトの土台として適しています。

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(
        headless=True,
        proxy={
            "server": "http://gw.dataimpulse.com:823",
            "username": "login",
            "password": "password",
        },
    )
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.inner_text("body"))
    browser.close()

認証付きプロキシの利用という観点で、3 つのツールを比較します。

ツール 認証付きプロキシ リクエストの検査 メンテナンス 最適な用途
素の Selenium 4 認証拡張機能のヘルパーが必要 なし アクティブ シンプルなフロー、リクエスト捕捉なし
Selenium Wire 組み込み、オプション 1 つ リクエストとレスポンスへの完全なアクセス アーカイブ済み、バージョンを固定 既存の Selenium コードでのデバッグとヘッダー制御
Playwright 組み込み、ネイティブ ルートとレスポンスの傍受 アクティブ 最新のツールを求める新規プロジェクト

移行の目安として、認証付きプロキシだけが必要でリクエストの捕捉が不要なら、認証拡張機能を使う素の Selenium が最も軽量で、メンテナンスが継続しているコードを使えます。トラフィックの検査や書き換えが必要で、新規に始めるなら、Playwright はバージョン固定の負担なくそれらをネイティブに提供します。リクエストレベルの制御を作り直すコストが高い既存の Selenium コードベースでは、Selenium Wire を継続利用してください。どのツールでも、利用する IP を選ぶ際は、住宅用プロキシデータセンタープロキシモバイルプロキシをターゲットの防御レベルに合わせて比較してください。

ツール別の認証付きプロキシの扱い

よくある質問

Selenium Wire で認証付きプロキシを設定するには?

ドライバーの作成時に seleniumwire_options で、login:password@host:port 形式の http と https の URL を指定したプロキシの dict を渡し、localhost 用に no_proxy を追加します。拡張機能や認証ダイアログへの回避策は不要です。

なぜ Selenium Wire は blinker の ImportError で失敗するのか?

blinker 1.8 では、Selenium Wire が起動時に import する内部名が削除されました。selenium-wire と selenium のバージョンも固定し、blinker は 1.8 未満、たとえば blinker==1.7.0 に固定してください。

Selenium Wire は今もメンテナンスされているのか?

元のプロジェクトはアーカイブ済みで、積極的なメンテナンスは行われていません。固定したバージョンでは現在も動作しますが、Selenium や Chrome を更新する際は隔離環境でテストし、新規プロジェクトではメンテナンスが継続しているフォークや Playwright を検討してください。

プロキシが実際に使われているか確認するには?

ドライバーで api.ipify.org などの IP 応答サービスを開き、返されたアドレスが自分のものではなくプロキシのものであることを確認します。driver.requests を確認して、トラフィックがゲートウェイを通過したことも確かめられます。

Selenium Wire は HTTPS トラフィックを読めるのか?

はい。man-in-the-middle プロキシとして動作し、自身のルート証明書を追加して HTTPS の本文を復号します。certificate pinning を使うサイトはこれを拒否するため、そのようなホストでは捕捉を無効にしてください。

DataImpulse が適さないのはどんなときか?

静的な ISP プロキシ、完全マネージド型のスクレイピング API、銀行や政府のサイトへのアクセスが必要な場合、DataImpulse は適していません。公開データの収集やコンテンツへのアクセス向けに、ローテーティング住宅用、モバイル、データセンタープロキシを提供しています。

信頼できるプロキシ経由で Selenium Wire を実行する

Selenium Wire で得られる結果は、利用する IP の品質にも左右されます。倫理的に調達された住宅用、モバイル、データセンター IP を経由して、ブラウザ自動化を 1 GB あたり 1 ドルからの従量課金でルーティングできます。DataImpulse アカウントを作成し、ローテーティングまたはスティッキーセッションで始めましょう。


Share article: