ヘッドレスブラウザ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をたたくリクエストを試すことができます。

splash.png

サイトにアクセスしてみる

まずはUI上の Render me! ボタンをおしてみてください。
下記のようにsplashを実行した結果を見ることができます。

splash-execute.png

デフォルトで用意されているブラウジングのための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

ここでは

  1. 与えられたurlを訪れる
  2. 0.5秒待つ
  3. 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

ここでは

  1. エリア選択のurlを訪れる
  2. 埼玉のチェックボックスをクリックして市町区村を選ぶボタンを押して、検索結果を見るボタンが現れるのを待つ
  3. 市町区村をすべて選択するチェックボックスをクリックして検索ボタンを押し、物件一覧画面が現れるまで待つ
  4. htmlとpngのリソースを返す

といった処理が記述されています。
実行結果は下記です

splash-script.png

まとめ

上記のように、Lua言語によって細かいブラウジングの挙動を記述することができます。
また、splashはデフォルトで並列処理をサポートしているので、splashのAPIに複数リクエストを送った場合でもブラウジングを効率的にさばきます。
そして、splashのAPIへのリクエストをラップするためのscrapyのプラグインもあるので、よかったらためしてみてください。