ヘッドレスブラウザsplashが便利だったので知見を共有します
モチベーション
jsで構成されたサイトをスクレイピングしたいなと思い立った時、seleniumがデファクトの選択肢として挙げられると思います。
しかしseleniumの含めヘッドレスブラウザはブラウジングが入ってくるので処理がそれなりに遅くなってしまいます。大量のページをスクレイピングする用途では不向きです。
そこで、サイトをしっかりブラウジングしながらもパフォーマンスを両立するヘッドレスブラウザという要件でseleniumの代わりをさがしていたところ、splashに白羽の矢が立ちました。
splashとは
scrapyの開発元であるscrapinghub社が開発しているスクレイピングに特化したヘッドレスブラウザです。
splashは他のヘッドレスブラウザとは毛色が違い、Dockerで配布されるHTTP APIです。
ドキュメントにも書いてあるように
- 並列でページを処理する
- ページレンダリング速度を上げるためにアドブロックや画像表示をオフにできる
- Luaで細かいブラウジング用のスクリプトをかける
といったスクレイピングに嬉しい機能がたくさん盛り込まれています。
触って見る
ドキュメントの通り、docker経由でインストールしてみましょう。
docker pull scrapinghub/splash
docker run -p 8050:8050 -p 5023:5023 scrapinghub/splash
すると、 localhost:8050
でsplashのUIにアクセスできます。
このUIからsplashのAPIをたたくリクエストを試すことができます。
サイトにアクセスしてみる
まずはUI上の Render me!
ボタンをおしてみてください。
下記のようにsplashを実行した結果を見ることができます。
デフォルトで用意されているブラウジングのためのLuaスクリプトは下記です。
function main(splash, args)
assert(splash:go(args.url))
assert(splash:wait(0.5))
return {
html = splash:html(),
png = splash:png(),
har = splash:har(),
}
end
ここでは
- 与えられたurlを訪れる
- 0.5秒待つ
- html, png, harといったリソースを返す
といった処理が記述されています。
ブラウジングスクリプトを書いてみる
Luaによるブラウジングのスクリプトを書いてみましょう。
以下は不動産サイトの都道府県を選択するページを訪れて不動産物件の一覧ページを取得するスクリプトです。
先ほどのGoogleのリンクを http://chintai.mhe.co.jp/search/area.php?area_cd=03
に書き換え、scriptの項目を下記に書き換えてください。
function main(splash)
splash:go(splash.args.url)
local area = splash:select('.items input#id11')
area:click()
local submit_area = splash:select('.tools-wrap input[type=image]')
submit_area:click()
while not splash:select('input[alt="検索結果を見る"]') do
splash:wait(0.1)
end
local city = splash:select('h4.city_name input#id_saitama')
city:click()
local submit_city = splash:select('section.button input[type=image]')
submit_city:click()
while not (splash:select('section.pager-head') and splash:select('form#search_form')) do
splash:wait(0.1)
end
return {html = splash:html(), png = splash:png()}
end
ここでは
- エリア選択のurlを訪れる
- 埼玉のチェックボックスをクリックして市町区村を選ぶボタンを押して、検索結果を見るボタンが現れるのを待つ
- 市町区村をすべて選択するチェックボックスをクリックして検索ボタンを押し、物件一覧画面が現れるまで待つ
- htmlとpngのリソースを返す
といった処理が記述されています。
実行結果は下記です
まとめ
上記のように、Lua言語によって細かいブラウジングの挙動を記述することができます。
また、splashはデフォルトで並列処理をサポートしているので、splashのAPIに複数リクエストを送った場合でもブラウジングを効率的にさばきます。
そして、splashのAPIへのリクエストをラップするためのscrapyのプラグインもあるので、よかったらためしてみてください。