Socks5Proxy

Seleniumプロキシ設定、ChromeとFirefoxにSOCKS5・HTTPプロキシ接続

このガイドではSelenium 4でChromeとFirefoxを実行する際、Socks5ProxyのHTTPプロキシとSOCKS5プロキシを接続する方法と、Chrome実行引数がプロキシパスワードを受け取らないためIP認証を使用する設定を説明します。

Seleniumでプロキシ認証が難しい理由は何ですか?

Chromeは--proxy-server実行引数でプロキシアドレスを受け取りますが、その中のユーザー名とパスワードは受け取りません。ユーザー名とパスワードが必要なプロキシに接続すると、ブラウザが認証ウィンドウを表示しますが、Seleniumではこのウィンドウに値を入力するのが難しいです。

最もクリーンな解決策はIP認証です。ダッシュボードにSeleniumが実行されるサーバーやPCのIPv4を登録すると、プロキシがそのIPの接続をユーザー名とパスワードなしで受け入れます。すると、Chromeにはip:portだけを入力すれば済みます。最大10個のIPを登録できるので、複数のサーバーで一緒に使えます。

例ではIP 198.51.100.23、HTTPポート8000、SOCKS5ポート1080を使用します。

pip install selenium

ChromeにHTTPプロキシを接続するにはどうすればいいですか?

IP認証を登録した後、ChromeOptionsに--proxy-server引数でアドレスを指定します。Selenium 4.6以上ではSelenium Managerが適切なchromedriverを自動的にダウンロードするので、別途インストールする必要はありません。

ヘッドレスモードでも同じ引数がそのまま適用されます。接続確認はIP確認アドレスを開き、画面のIPがプロキシIPかどうかを確認します。

from selenium import webdriver
from selenium.webdriver.common.by import By

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")  # this machine's IP is authorized in the dashboard
opts.add_argument("--headless=new")

driver = webdriver.Chrome(options=opts)
try:
    driver.get("https://api.ipify.org")
    print(driver.find_element(By.TAG_NAME, "body").text)  # should print the proxy IP
finally:
    driver.quit()

ChromeでSOCKS5プロキシを使うにはどうすればいいですか?

--proxy-serverにsocks5://アドレスを指定します。ChromeはSOCKS5使用時にドメイン名解決をプロキシ側で行いますが、一部環境では内部DNS解決が残る可能性があるため、--host-resolver-rules引数でローカル名前解決をブロックする方法がよく使われます。

SOCKS5もIP認証で接続します。ChromeはSOCKSプロキシのユーザー名とパスワード認証をサポートしていないためです。

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=socks5://198.51.100.23:1080")
# make sure host names are resolved through the proxy
opts.add_argument('--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE 198.51.100.23')

driver = webdriver.Chrome(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

Firefoxにはどうやって接続しますか?

Firefoxは環境設定値でプロキシを指定します。network.proxy.typeを1(手動)に設定し、HTTPまたはSOCKSアドレスとポートを入力します。SOCKS5はnetwork.proxy.socks_versionを5に、network.proxy.socks_remote_dnsをTrueに設定すると、プロキシ側で名前を確認します。

Firefoxも実行設定でプロキシパスワードを入力する方法がないため、IP認証を使用するのが最も簡単です。

from selenium import webdriver

opts = webdriver.FirefoxOptions()
opts.set_preference("network.proxy.type", 1)
opts.set_preference("network.proxy.socks", "198.51.100.23")
opts.set_preference("network.proxy.socks_port", 1080)
opts.set_preference("network.proxy.socks_version", 5)
opts.set_preference("network.proxy.socks_remote_dns", True)

driver = webdriver.Firefox(options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

複数のブラウザを異なるIPで同時に起動するにはどうすればいいですか?

ブラウザごとに異なるプロキシアドレスを設定して個別に実行します。以下のコードはAPIでip:portリストを取得し、ブラウザ3つを異なるIPで起動する例です。ブラウザ1つがメモリを多く消費するので、サーバーサイズに合わせて同時起動数を決めてください。

ブラウザを長時間使用する作業では、1つのブラウザに1つのIPを固定し、作業が終わるまで変更しないのがおすすめです。

import requests
from selenium import webdriver

KEY = "YOUR_API_KEY"
lines = requests.get(
    "https://socks5proxy.io/api/v1/proxies/download",
    params={"format": "ip:port", "protocol": "http"},
    headers={"Authorization": "Bearer " + KEY},
    timeout=30,
).text.split()

drivers = []
for line in lines[:3]:
    opts = webdriver.ChromeOptions()
    opts.add_argument("--headless=new")
    opts.add_argument("--proxy-server=http://" + line)
    drivers.append(webdriver.Chrome(options=opts))

for d in drivers:
    d.get("https://api.ipify.org")
    print(d.page_source)
    d.quit()

ユーザー名・パスワード認証を必ず使用する必要がある場合はどうすればよいですか?

IP認証を使用できない環境、例えば出ていくIPが頻繁に変わる環境では、2つの方法があります。1つ目はselenium-wireのような中間プロキシライブラリで認証情報を代わりに入れる方法、2つ目は同じサーバー上で認証なしのローカル中継プロキシを立ち上げ、Chromeはローカルアドレスで、ローカル中継はユーザー名・パスワードでSocks5Proxyに接続する方法です。

どちらの方法も管理要素が1つ増えるため、可能であれば固定IPサーバーでIP認証を使用するのが最もシンプルで高速です。

ブラウザ環境をその国に合わせるには何を設定すればいいですか?

IP国に合わせてChromeの--lang引数とAccept-Language設定を変更すると、ページがその国の言語で開きます。タイムゾーンが重要なサイトの場合、CDPコマンドEmulation.setTimezoneOverrideでタイムゾーンも合わせることができます。

ウィンドウサイズは--window-size引数で設定し、スマートフォン画面が必要な場合はモバイルデバイスのエミュレーション設定を使いましょう。これらの値を国別設定としてまとめておけば、同じテストを複数の国で一貫して実行できます。

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")
opts.add_argument("--lang=de-DE")
opts.add_argument("--window-size=1366,900")

driver = webdriver.Chrome(options=opts)
driver.execute_cdp_cmd("Emulation.setTimezoneOverride", {"timezoneId": "Europe/Berlin"})
driver.get("https://example.com/")
driver.quit()

Selenium Gridやリモートブラウザでも同じ設定を使用しますか?

はい。ChromeOptionsとFirefoxOptionsはリモート実行でもそのまま引き継がれます。webdriver.Remoteに同じオプションを指定すると、Gridノードのブラウザがそのプロキシで接続します。この時、IP認証に登録するIPはコードを実行するPCではなく、ブラウザが実際に実行されるGridノードの出口IPです。

複数のノードがある場合は、各ノードのIPをすべて登録してください。最大10個まで登録できます。クラウドノードのIPが頻繁に変わる環境では、ノードに固定IPを割り当てると管理が楽になります。

from selenium import webdriver

opts = webdriver.ChromeOptions()
opts.add_argument("--proxy-server=http://198.51.100.23:8000")  # authorize the Grid node IP, not this machine
driver = webdriver.Remote(command_executor="http://grid.example.internal:4444", options=opts)
driver.get("https://api.ipify.org")
print(driver.page_source)
driver.quit()

接続ができないときは何を確認しますか?

ERR_PROXY_CONNECTION_FAILEDはアドレスやポートが間違っている場合が多いです。HTTPアドレスにSOCKS5ポートを設定していないか確認してください。ERR_TUNNEL_CONNECTION_FAILEDが発生したり、認証ウィンドウが表示されたりする場合は、IP認証に登録したIPと実際に出ていくIPが異なる場合です。サーバーでcURLを使ってapi.ipify.orgをプロキシなしで開き、出ていくIPを確認してその値を登録してください。

クラウドサーバーは再起動すると発信IPが変わる可能性があります。固定IPを使用するか、IPが変わるときにダッシュボードの登録リストも一緒に変更してください。

Seleniumプロキシ設定、Chrome・Firefox接続方法 | Socks5Proxy