work.log

元エンジニアの備忘録的ブログ

BrowserMob Proxyを使ったアクセス解析に影響を与えないSeleniumのスクレイピングメモ

投稿:

SeleniumHeadless Chromeを使う時に、アクセス解析に影響を与えないようにスクレイピングするにはどうしたら良いかを調べました。

今のWebサイトってJavaScriptをほぼ必ず使っているので、スクレイピングもSeleniumとChromeを使った方が都合が良い場合が多いですが、Google Analyticsとかを始めとするアクセス解析に思いっきり影響が出てしまったので急遽対処する事に。

所有サイトでテストしておいて良かった…

調べるとBrowserMob Proxyを使えばアクセス解析を回避出来るとわかったのですが、導入までの情報が少なかったのでメモする事にしました。

環境は「Linux (CentOS) + Python + Selenium + Chrome (Headless)」で試しています。

Selenium + Chromeでアクセス解析を除外する方法

スクレイピング時にアクセス解析を除外する方法はいくつかあります。

  1. Google Analytics側の設定でクローラーのIPを除外する
  2. Chrome側でJavaScriptの実行を無効にする
  3. Google謹製のオプトアウトプラグインをChromeにインストールする
  4. プロキシを使いそこでアクセス解析のタグを除外する

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}]
参考にしたページ
github browsermob-proxy

Seleniumを高頻度で使うならBrowserMob Proxyは立ち上げっぱなしの方が効率良いかもしれません。

以上、Seleniumでアクセス解析を回避するメモでした。

コメント

コメントを残す

よく読まれている記事

  • 本日
  • 週間
  • 月間