Selenium と Ruby でプロキシを使用する
概要
プロキシサーバー経由で Selenium の Make リクエストを取得しようとしていますが、うまく動作しないようです。
このコードは応答を受け取りますが、プロキシを使用していません
Selenium::WebDriver.logger.level = :info
proxy = Selenium::WebDriver::Proxy.new(
:http => "http://username:password@host:port",
:ssl => "http://username:password@host:port"
)
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
proxy: proxy,
'goog:chromeOptions' => {
'args' => ['headless', 'no-sandbox', 'disable-gpu', 'window-size=1920,1080']
}
)
driver = Selenium::WebDriver.for(:chrome, :capabilities => caps)
driver.navigate.to "https://www.showmyip.com/"
2021-06-21 12:51:16 INFO Selenium -> POST session
2021-06-21 12:51:16 INFO Selenium >>> http://127.0.0.1:9515/session | {"capabilities":{"alwaysMatch":{"proxy":{"proxyType":"manual","httpProxy":"http://username:password@host:port","sslProxy":"http://username:password@host:port"},"browserName":"chrome","goog:chromeOptions":{"args":["headless","no-sandbox","disable-gpu","window-size=1920,1080"]}}}}
2021-06-21 12:51:16 INFO Selenium <- {"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"91.0.4472.114","chrome":{"chromedriverVersion":"91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs/branch-heads/4472@{#1462})","userDataDir":"/tmp/.com.google.Chrome.8Qfzwu"},"goog:chromeOptions":{"debuggerAddress":"localhost:46057"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"linux","proxy":{"httpProxy":"http://username:password@host:port","proxyType":"manual","sslProxy":"http://username:password@host:port"},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"b5a74fa8a44d298fb1fbffcc0516df83"}}
2021-06-21 12:51:16 INFO Selenium -> POST session/b5a74fa8a44d298fb1fbffcc0516df83/url
2021-06-21 12:51:16 INFO Selenium >>> http://127.0.0.1:9515/session/b5a74fa8a44d298fb1fbffcc0516df83/url | {"url":"https://www.showmyip.com/"}
2021-06-21 12:51:18 INFO Selenium <- {"value":null}
プロキシ文字列からスキームを削除しても同じ問題が発生します
2021-06-21 14:47:24 INFO Selenium >>> http://127.0.0.1:9515/session | {"capabilities":{"alwaysMatch":{"proxy":{"proxyType":"manual","httpProxy":"username:password@host:port","sslProxy":"username:password@host:port"},"browserName":"chrome","goog:chromeOptions":{"args":["headless","no-sandbox","disable-gpu","window-size=1920,1080"]}}}}
2021-06-21 14:47:24 INFO Selenium <- {"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"91.0.4472.114","chrome":{"chromedriverVersion":"91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs/branch-heads/4472@{#1462})","userDataDir":"/tmp/.com.google.Chrome.aVNdyH"},"goog:chromeOptions":{"debuggerAddress":"localhost:33363"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"linux","proxy":{"httpProxy":"username:password@host:port","proxyType":"manual","sslProxy":"username:password@host:port"},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"3d95da424ededc7f0a9f59dd8e20386d"}}
2021-06-21 14:47:24 INFO Selenium -> POST session/3d95da424ededc7f0a9f59dd8e20386d/url
2021-06-21 14:47:24 INFO Selenium >>> http://127.0.0.1:9515/session/3d95da424ededc7f0a9f59dd8e20386d/url | {"url":"https://www.showmyip.com/"}
2021-06-21 14:47:25 INFO Selenium <- {"value":null}
私もこのアプローチを試しました
client = Selenium::WebDriver::Remote::Http::Default.new
client.proxy = Selenium::WebDriver::Proxy.new(
:http => "http://username:password@host:port",
:ssl => "http://username:password@host:port"
)
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
'goog:chromeOptions' => {
'args' => ['headless', 'no-sandbox', 'disable-gpu', 'window-size=1920,1080']
}
)
driver = Selenium::WebDriver.for(:remote, :http_client => client, :capabilities => caps)
driver.navigate.to "https://www.showmyip.com/"
これにより、次の 502 エラーが発生します。私が使用しているプロキシは Net/HTTP で動作するため、問題があるとは思えません
/home/will/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/selenium-webdriver-4.0.0.beta4/lib/selenium/webdriver/remote/http/common.rb:93:in `create_response': unexpected response, code=502, content-type="text/html" (Selenium::WebDriver::Error::WebDriverError)
<html><head><title>502 Bad Gateway</title></head>\r
<body><h2>502 Bad Gateway</h2><h3>Host Not Found or connection failed</h3></body></html>
同じコードを使用して意図的に間違ったユーザー名またはパスワードを入力すると、このエラーが発生します
/home/will/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/selenium-webdriver-4.0.0.beta4/lib/selenium/webdriver/remote/http/common.rb:93:in `create_response': unexpected response, code=407, content-type="text/html" (Selenium::WebDriver::Error::WebDriverError)
<html><head><title>407 Proxy Authentication Required</title></head>\r
<body><h2>407 Proxy Authentication Required</h2><h3>Access to requested resource disallowed by administrator or you need valid username/password to use this resource</h3></body></html>
さらに詳しく調べてみると、Selenium は認証のあるプロキシを無視しているようです。
proxy_chain_rb を使用して、実際のプロキシにリダイレクトする認証なしでローカルホスト上にプロキシを設定すると機能するようです。
これは理想的な解決策ではありません。リクエストごとに異なるプロキシを使用する予定ですが、私の知る限り、リクエストごとにプロキシ サーバーを起動する必要があり、これには数秒かかります。
real_proxy = "http://username:password@host:port"
server = ProxyChainRb::Server.new
generated_proxy = server.start(real_proxy)
proxy = {
http: generated_proxy,
ssl: generated_proxy
}
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
proxy: proxy,
'goog:chromeOptions' => {
'args' => ['headless', 'no-sandbox', 'disable-gpu', 'window-size=1920,1080']
}
)
driver = Selenium::WebDriver.for(:chrome, :capabilities => caps)
driver.navigate.to "https://www.showmyip.com/"
解決策
Firefox ブラウザで Capybara と Selenium を使用してこれを実現できます。これをどのようにして作成できたかを次に示します。
次のコードを追加します。
Capybara.register_driver :proxy_firefox_driver do |app|
real_proxy = "http://user:[email protected]:123456"
server = ProxyChainRb::Server.new
generated_proxy = server.start(real_proxy)
formatted_proxy = generated_proxy.gsub('http://','')
proxy = Selenium::WebDriver::Proxy.new(http: formatted_proxy)
desired_caps = Selenium::WebDriver::Remote::Capabilities.firefox({
firefox_profile: "default",
proxy: proxy
})
Capybara::Selenium::Driver.new(app, {:browser => :firefox, :desired_capabilities => desired_caps})
end
そして最後に重要なことですが、プロキシ経由で HTTP を実行します。
url = 'https://www.etsy.com/listing/1588234442/'
Capybara.current_driver = :proxy_firefox_driver
session = Capybara::Session.new(:proxy_firefox_driver)
session.visit(url)
これは基本的に、実際のプロキシを指すローカルプロキシを作成することです。javascript(nodejs)は、(URL経由で)簡単に認証を使用してプロキシに接続するためのソリューションを提供しているようです。RubyとPythonの両方のSeleniumは、それらほどフレンドリーではないようです認証プロキシにすべきですが、これは印象的であり、この投稿と提起された提案のおかげで、それを見つけるのにかなりの時間を要しました。
このライブラリはrubygems (proxy_chain_rb) に移動されました。
しかし、この人は github (proxy_chain) にフォークを持っています。
これがお役に立てば幸いです。Selenium のような大きなライブラリが Javascript 以外の言語で意図どおりに動作しないとは予想できないほど、確かに少し困難でした。