第12章 ScrapyとJavaScript

はじめに

ここでは、JavaScriptで生成されるHTMLページをスクレイピングすることを手助けしてくれるSplashの使い方をまとめておきます。Scrapyはlxmlベースなので、JavaScriptを実行するなどはできません。そのため、JavaScriptを実行して結果をスクレイピングするためには、JavaScriptを実行し、実行後のHTMLをScrapyに渡す必要があります。そのJavaScriptを実行してHTMLを返すことをSplashはやってくれます。

DockerとSplashのインストール

SplashはWebKitがベースのヘッドレスブラウザを組み込んだサーバーです。ヘッドレスブラウザというのは、サーバ環境などでHTMLをレンダリングするためにバックグラウンドで動作させるブラウザなので、GUIの画面をありません。機械のためのブラウザというイメージでしょうか。Splashは下記のようなことができるようです。

  • 複数のウェブページを並行して処理できる。

  • HTML の結果を取得したり、スクリーンショットを撮影したりできる。

  • 画像を読み込みをOFFにしたり、Adblock Plus ルールを使用してレンダリングを高速化できる。

  • ページコンテキストでカスタム JavaScript を実行できる。

  • Luaブラウジングスクリプトを書ける。

  • Splash-Jupyter Notebooks で Splash Lua スクリプトを開発できる。

  • レンダリングの詳細情報をHAR形式で取得できる。

では、公式のドキュメントに従ってDockerを利用した方法で行います。まずは、Dockerのアカウントを作ってログインし、DockerHubからDocker for Macをインストールします。

$ docker version
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b
 Built:             Wed Mar 11 01:21:11 2020
 OS/Arch:           darwin/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       afacb8b
  Built:            Wed Mar 11 01:29:16 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

Docker hubに置かれているScrapinghub社のscrapinghub/splashイメージをdocker pullコマンドでダウンロードします。docker runコマンドでコンテナを作って実行します。ポートの意味は下記のとおりです。5023がtelnet、8050がhttp、8051がhttpsです。

http://0.0.0.0:8050にアクセスして、コンテナ内のサーバーが起動していることを確認します。

Dockerのプロセスも確認しておきます。

次はscrapy_splashをインストールします。

これで必要なものがインストールできました。

Javascriptで動的に生成されるページ

Scapye内でSplashを使用する場合、基本的には下記の順序で行います。

  1. scrapy_splashライブラリをインストール

  2. Splashのサーバーを起動する(Dockerコンテナ)

  3. settings.pyに必要な情報を記載する

  4. SpiderでRequestクラスではなく、SplashRequestクラスを利用する。

  5. Luaスクリプトでブラウザを操作する

ここでは、偉人の名言サイト"Quotes To Scrape"のJavaScript版ページを対象にします。このサイトは、Webページ内にJavaScriptが仕込まれており、生のHTMLには名言は含まれていません。Webブラウザでページがレンダリングされたときに。JSON形式のデータオブジェクトを反復処理してDOMを作成することで、サイトに名言のブロックが作られる仕様になっています。そのため、Scrapyでそのままデータを抽出することはできません。

ほかにも下記のようなページもJavaScriptで動的にHTMLが生成されます。よく見るような車の通販サイトです。このページでは左側のボックスにチェックを入れることで表示される車が変更されます。

例えば、2020年のFORDにチェックを入れると表示が変更されます。このようなページをスクレイピングしたいのであれば、Splashを使って、Luaスクリプトでブラウザを操作する必要があります。他の方法としては、リクエストするURLを書き換えれば、Splashを使わなくてもスクレイピングできます。

Scrapy×Splashのサンプルコード

まずはいつもどおりプロジェクト作成します。

settings.pyにSplashの情報を追記します。

クローラーのコードはこのようになります。いつもと違う点は、scrapy_splashライブラリが呼ばれ、SplashRequest()が使用され、Luaスクリプトがある点です。ここでは、Luaスクリプトでなくてもページを移動できますが、サンプルとしてボタンをクリックするLuaスクリプトを記載しています。

SplashRequest()render.htmlはJavaScriptでレンダリングされたページのHTMLを返す設定です。Luaスクリプトについてはドキュメントの詳細を確認してください。それではクローラーを実行していきましょう。

問題なく100個分の名言が取得できています。

最終更新

役に立ちましたか?