第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: fec3683Docker 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を使用する場合、基本的には下記の順序で行います。
scrapy_splashライブラリをインストールSplashのサーバーを起動する(Dockerコンテナ)
settings.pyに必要な情報を記載する
SpiderでRequestクラスではなく、SplashRequestクラスを利用する。
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個分の名言が取得できています。
最終更新
役に立ちましたか?