みなさん、認証プロキシはお好きですか?
私はもちろん嫌いです。が、まあそういう環境がまだまだ多数あるということも知っておりますし諸事情を考えるとやむを得ないこともあるのかなーとは思います。
そういうところでSeleniumによるGUI自動操作を行いたいというニーズがありまして……Google先生に聞いてみるといくつか答えが得られるのです。が、仕様変更があったり条件がちょっと違ったりとかしてうまくいかない。しばらく煮詰まっていたのですが、うまくいったのでご紹介。
結論としては:
を使ってこんなコードで良さそうです*1。事前に次のような変数は初期化されているものとします。
変数名 | 意味 |
---|---|
proxyServer |
プロキシのサーバー名 |
proxyPort |
プロキシのポート番号 |
username |
プロキシ認証ユーザー名 |
password |
プロキシ認証パスワード |
// BrowserMob Proxyにて、認証プロキシにチェーンするプロキシを作成する // 参考: // https://github.com/lightbody/browsermob-proxy/blob/master/browsermob-core/src/test/groovy/net/lightbody/bmp/proxy/ChainedProxyAuthTest.groovy BrowserMobProxy bmp = new BrowserMobProxyServer(); // Don't use InetSocketAddress.unresolved(), use new InetSocketAddress instead bmp.setChainedProxy(new InetSocketAddress(proxyServer, proxyPort)); bmp.chainedProxyAuthorization(username, password, AuthType.BASIC); bmp.setTrustAllServers(true); bmp.start(); // 動作しているプロキシをSeleniumのProxyクラスに変換して登録 Proxy proxy = ClientUtil.createSeleniumProxy(bmp); proxy.setNoProxy("localhost"); // Proxy除外設定もかける DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(CapabilityType.PROXY, proxy); System.setProperty("webdriver.chrome.driver", "./driver/linux/chromedriver"); WebDriver driver = new ChromeDriver(cap); // 古いスタイルだというのは知っております……。 driver.get("http://www.google.com"); // サンプル // ここにいろんな操作を書く driver.quit(); bmp.stop();
探し方が良くないのかもしれないのですがBrowserMob ProxyのEmbeddedモード(Javaのコード内でライブラリとして利用する方法)がなんかいい情報がなくて、あーでもないこーでもないと試行錯誤していたのですが、コード片上にコメントで書いてあるとおり ChainedProxyAuthTest.groovy
っていうズバリのテストコードがあって、それを参考にしました。
BrowserMobProxy.setChainedProxy()
に渡すための InetSocketAddress
をどうやって生成するかについては、BrowserMob Proxyの過去のIssueに答えがありました*2。
枝葉ですが、私自身はSeleniumのラッパークラスであるSelenideを使ってるので、このときのプロキシ設定は DesiredCapabilities
を使う代わりに WebDriverRunner.setProxy()
すればうまくいきます。
試行錯誤の内容
- 「自動テストスクリプトからは認証なしプロキシとして見えて、実際の認証プロキシにチェーンしてそちらに認証情報を渡す」小さなプロキシ(以下チェーンプロキシ)を立てるって方法が複数ヒットする。たしかにうまく行くのはわかるけど、いろいろあってすごくやりにくいのでこの方式は「どうしようもない場合の切り札」として検討後回し。
- Seleniumの
Proxy.setSocksUsername()
/Proxy.setSocksPassword()
を使えるって情報が複数ヒットするも、正しく動作せず。まあSocksって名前だしねえ……。もしかしたらプロキシ認証がBasic認証じゃない場合は通ったりするのかしら。 - Chromeには
--proxy-auth
ってコマンドライン引数がある……という情報があったが、指定しても無視されるし、頼りのList of Chromium Command Line Switches にはそんなオプションはない。廃止された? - 環境変数
http_proxy
で指定すれば……という意見もあったけど、今回、操作したい対象そのものはプロキシの中にあって、そこから呼ばれてるJSとかCSSが外部……という状態なので除外設定が必要。環境変数だとそういう制御ができない気がして、そっち側の調査はあまり深堀してない。 - 手詰まりなのでSeleniumHQのSlackで聞いてみたところ、……Seleniumはそういう機能ないのでBrowserMob Proxyを使うといいよと助言をもらう。
- ふむふむと調べると……。テンパっていた中で超斜め読みして、うーんこれは結局チェーンプロキシを立てる話なのでは、と誤読して、ちゃんと調べるのは後回しにした。
- 色々忙しくしてたら本件納期が差し迫っているのに解決のめど立ってなくてやばい。そんなわけでナナメ読みしたドキュメントを少し丁寧に読んだら、BrowserMob Proxyにはプロセスとして動作するモードとJava埋め込みできるモードがあって、後者ならプロセス別立て要らないのかも? しかも「Using with Selenium」なんて項目もあるし。ちょっと期待。
- ざくっと調査すると次の記事がヒット。この記事のコード例は今のBrowserMob Proxyだとまったく通らない*3けど、やりたいことはできるようなので真面目に書き方を調べる。
- ドキュメントを読んでもいまいち使い方わかんないしGoogleで探してもずばりのページはないなあ……というかJavaDocとかはないのか、と思って調べたけど、考えてみればソース読めばいいんだよね。ということで読む。
- というかソース読んでるぐらいならテスト見れば使い方わかるんじゃね? と思って、
src/test
以下を探したら正解! - 真面目に調べ始めてからコードをいじってあーでもないこーでもないってしてた時間はそんなには長くないかな。2〜3時間? 返す返すもテンパってたときにドキュメントをちゃんと読まなかったのが悔しい。
- コード書くよりめんどくさかった作業は、検証用に手元に認証プロキシがある環境を作ることでした。結局 GitHub - sameersbn/docker-squid: Dockerfile to create a Docker container image for Squid proxy server こいつを使って、
/etc/squid3/squid.conf
はホストにマウントして認証設定書いて、/etc/squid3/.htpasswd
はめんどくさかったのでコンテナ内部に直接作っちゃいましたが、これもホストにマウントすればよかったんだな。この話も気が向いたら書きます。
- コード書くよりめんどくさかった作業は、検証用に手元に認証プロキシがある環境を作ることでした。結局 GitHub - sameersbn/docker-squid: Dockerfile to create a Docker container image for Squid proxy server こいつを使って、
あとから考えるとBrowserMob ProxyをSeleniumから使うことについては:
定番のこの本に書いてあるので、もっと早く気づいてもよかった。BrowserMob Proxyはパフォーマンス測定とかにも使うやつなので、あんまり印象に残ってなかったんですよね(いいわけ)。