SeleniumでHeadless Chromeを使う時に、アクセス解析に影響を与えないようにスクレイピングするにはどうしたら良いかを調べました。
今のWebサイトってJavaScriptをほぼ必ず使っているので、スクレイピングもSeleniumとChromeを使った方が都合が良い場合が多いですが、Google Analyticsとかを始めとするアクセス解析に思いっきり影響が出てしまったので急遽対処する事に。
所有サイトでテストしておいて良かった…
調べるとBrowserMob Proxyを使えばアクセス解析を回避出来るとわかったのですが、導入までの情報が少なかったのでメモする事にしました。
環境は「Linux (CentOS) + Python + Selenium + Chrome (Headless)」で試しています。
目次
スポンサーリンク
Selenium + Chromeでアクセス解析を除外する方法
スクレイピング時にアクセス解析を除外する方法はいくつかあります。
- Google Analytics側の設定でクローラーのIPを除外する
- Chrome側でJavaScriptの実行を無効にする
- Google謹製のオプトアウトプラグインをChromeにインストールする
- プロキシを使いそこでアクセス解析のタグを除外する
1についてはこちらでコントロール出来る話じゃないので無理。2もJavaScriptを使わないのだったらSeleniumを使わなくても良くなるので除外。
Google Analyticsを使ったアクセス解析を想定した場合だと3が簡単確実なのですが、残念な事にヘッドレスブラウザはエクステンションが使えないのでこれも今回は無理。
という事で4のプロキシを使う方法を採用する事にしました。次で各種セットアップと実装コードを解説します。
BrowserMob Proxyのインストール
BrowserMob ProxyはJava製のプロキシですが、Pythonからも使う事が出来ます。
まずはCentOSにJavaの実行環境とBrowserMob Proxyのインストールを行います。
Javaのインストール
Javaの実行環境はyumでサクッとインストールしちゃいます。
# yum install java
BrowserMob Proxyのインストール
BrowserMob Proxyは公式サイトからzipを落としきて適当なディレクトリに解凍し、実行権限を与えます。
$ wget https://github.com/lightbody/browsermob-proxy/releases/download/browsermob-proxy-2.1.4/browsermob-proxy-2.1.4-bin.zip $ unzip browsermob-proxy-2.1.4-bin.zip $ chmod 755 browsermob-proxy-2.1.4/bin/browsermob-proxy
Pythonモジュールのインストール
続いて、BrowserMob ProxyをPythonから使う為に必要なモジュールをインストールします。
# pip install browsermob-proxy # pip install psutil
準備はこれで完了です。
SeleniumでBrowserMob Proxyを使う
Selenium + ChromeでBrowserMob Proxyを使うコードを書いていきます。
from browsermobproxy import Server from selenium import webdriver from selenium.webdriver.chrome.options import Options import psutil import traceback def terminate_browsermob_processes(proxy, server): proxy.close() server.stop() for process in psutil.process_iter(): try: process_info = process.as_dict(attrs=['name', 'cmdline']) if process_info.get('name') in ('java', 'java.exe'): for cmd_info in process_info.get('cmdline'): if cmd_info == '-Dapp.name=browsermob-proxy': process.kill() except psutil.NoSuchProcess: pass if __name__ == '__main__': # BrowserMob Proxyのインストールパス proxy_path = './browsermob-proxy-2.1.4/bin/browsermob-proxy' # BrowserMob ProxyがListenするポート番号 (デフォルト: 8080) proxy_ooptions = {'port': 50000} options = Options() options.add_argument('--headless') options.add_argument('--no-sandbox') options.add_argument('--disable-gpu') options.add_argument('--ignore-certificate-errors') try: server = Server(proxy_path, options=proxy_ooptions) server.start() proxy = server.create_proxy() # Google Analyticsが利用するURLをblacklistに入れてアクセス解析タグを除外する proxy.blacklist('https?:\/\/www\.google-analytics\.com\/analytics\.js', 404) proxy.blacklist('https?:\/\/www\.googletagmanager\.com\/gtag\/js\?id=UA-.*', 404) options.add_argument('--proxy-server={0}'.format(proxy.proxy)) driver = webdriver.Chrome(options=options) # HTTP(S)通信の内容も取得したい場合 #proxy.new_har('google', options={'captureHeaders': True}) driver.get('https://worklog.be/') print(driver.title) # 通信内容を表示 #print(proxy.har) # ブラウザのログを取得して表示 log = driver.get_log('browser') print(log) except: traceback.print_exc() finally: driver.quit() # BrowserMob Proxyの関連プロセスを完全に停止する処理 terminate_browsermob_processes(proxy, server)
このスクリプトでアクセスするとこのようにアクセス解析タグを読み込めなかったというエラーがブラウザに出力されます。
[{'level': 'SEVERE', 'message': 'https://www.googletagmanager.com/gtag/js?id=UA-xxxxxxxxx-x - Failed to load resource: the server responded with a status of 404 (Not Found)', 'source': 'network', 'timestamp': 1551945420977}] もしくは... [{'level': 'SEVERE', 'message': 'https://www.google-analytics.com/analytics.js - Failed to load resource: the server responded with a status of 404 (Not Found)', 'source': 'network', 'timestamp': 1551945496909}]
アクセス解析はproxy.blacklistの部分で該当するURLを除外。正規表現が使えます。
Google Analyticsの解析タグはちょいちょい変わりますが、この2つを指定しておけばとりあえずは大丈夫だと思います。
BrowserMob ProxyはSeleniumでHTTPステータスコード等を取得したい場合に使うケースが多いようですので、その場合はproxy.new_harのメソッドで各種情報を取得できます。
最後に関連プロセスを停止する処理を挟んでいますが、proxy.close() server.stop() だけではJavaのゾンビプロセスが残るのでそれをkillする処理です。
こちらはLinuxとWindows兼用です。
BrowserMob ProxyとSeleniumの組み合わせは情報が少なくこれらを見つけるのに苦労しました😇
BrowserMob ProxyのREST APIを触ってみる
BrowserMob Proxyは単独でも動作するプロキシでREST APIも用意されています。
起動する時はこんな感じに。
$ ./browsermob-proxy-2.1.4/bin/browsermob-proxy -port 50000 Running BrowserMob Proxy using LittleProxy implementation. To revert to the legacy implementation, run the proxy with the command-line option '--use-littleproxy false'. [INFO 2019-03-07T21:31:27,241 net.lightbody.bmp.proxy.Main] (main) Starting BrowserMob Proxy version 2.1.4 [INFO 2019-03-07T21:31:27,291 org.eclipse.jetty.util.log] (main) jetty-7.x.y-SNAPSHOT [INFO 2019-03-07T21:31:27,336 org.eclipse.jetty.util.log] (main) started o.e.j.s.ServletContextHandler{/,null} [INFO 2019-03-07T21:31:27,502 org.eclipse.jetty.util.log] (main) Started SelectChannelConnector@0.0.0.0:50000
APIにアクセスして example.com をblacklistに登録してみます。
$ curl -X POST http://localhost:50000/proxy {"port":8081} $ curl -X PUT -d 'regex=https?:\/\/example\.com&status=404' http://localhost:50000/proxy/8081/blacklist $ curl -X GET http://localhost:50000/proxy/8081/blacklist [{"urlPattern":"https?:\\/\\/example\\.com","statusCode":404,"httpMethodPattern":null,"responseCode":404,"pattern":"https?:\\/\\/example\\.com","method":null}]
Seleniumを高頻度で使うならBrowserMob Proxyは立ち上げっぱなしの方が効率良いかもしれません。
以上、Seleniumでアクセス解析を回避するメモでした。
こんにちは。
BrowserMob Proxyで認証プロキシを使いたいときはどこにユーザー名とパスワードを入れればよいのでしょうか?
よろしくお願いします。
セレンさん
READMEを確認してみてください。
https://github.com/lightbody/browsermob-proxy
proxyUsername とか proxyPassword というパラメータがあるのでこの辺りかなと思います。
miuraさま
返信いただきありがとうございます!確認してみます。