第11章 Scrapy Tutorial3

はじめに

ここではScrapyの3つ目のチュートリアルとして、HTMLテーブルからのスクレイピング、画像のスクレイピング、JSONデータのスクレイピングなどを行います。

テーブルをスクレイピング

ここでは、下記のようにテーブル形式でレイアウトされているデータを、Scrapyでスクレイピングする方法をまとめます。このテーブルはWikipediaの都道府県の人口に表示されているテーブルです。

Wikipedia:都道府県の人口一覧

このようなテーブルデータのHTMLは簡単に紹介すると、下記のようなHTMLになっています。th(table header)タグテーブルのヘッダを表示し、tr(table row)タグで行をまとめ、td(table data)タグが各値を表示します。

そのため、このようなテーブルデータをスクレイピングするためには、これまでと同じ要領で、行ごとに値を持つtrをリストで取得し、それをループで回して、tdから各値を取得すれば良さそうです。

では、さきほど表示したWikipediaの都道府県の人口に表示されているテーブルをスクレイピングしていきます。Scrapyのプロジェクトを下記の通り作ります。

あとは、いつもどおりxpathで欲しい情報を取得するようにします。

それでは実行していきましょう。数秒で終了すると思います。中身を確認すると問題なく47都道府県の人口推移の情報を取得できています。

画像をスクレイピング

次は画像をスクレイピングしていきます。対象のサイトは、これまでも使ってきた架空のオンライン書店のサイトです。このサイトの下記書籍のタイトル画像を取得します。

まずはsettings.pyの内容を変更していきます。ITEM_PIPELINESIMAGES_STOREを追加します。ITEM_PIPELINESImagesPipelineは画像を扱えるようにするための設定です。IMAGES_STOREは画像の保存先を指定します。詳細はドキュメントを参照ください。ここではデスクトップに画像をダウンロードするようにしています。

Items.pyには、タイトル、URL、画像を受け取れるようにしておきます。タイトルを取得するのは、ダウンロードした画像の名前をタイトルで変更するためです。

books.pyでは、ItemLoader()をインスタンス化し、URLやタイトルをスクレイピングします。そして、スクレイピングした値をItemLoader()add_value()で渡します。

pipelines.pyでは、ダウンロードされた画像がランダムな文字列になってしまうので、書籍のタイトルを使って、変更しています。

アイテムはこのような形で返されるので、この情報をもとに上記の名前変更のパイプラインを定義しています。

クローラーを実行し、画像の保存先を確認します。このような形でjpgの画像データが保存されていることがわかります。

このようにScrapyは画像のダウンロードもできるので、収集したデータを使って画像の機械学習モデルを作るのにも非常に便利です。画像の著作権には気をつける必要がありますが、openCVと掛け合わせて、ダウンロードした画像が人の画像なのかを判定したりもできるようです。

JSONをスクレイピング

ECサイトなどをスクレイピングしていると、普通にアクセスする分には、金額が表示されているのに、クローラーとしてアクセスすると、金額の表示がなくなっていたりします。そのようなサイトを調べてみると、APIで金額を呼び出している場合があります。そのようなページから値をスクレイピングするためには、その金額を呼び出しているもとにリクエストを送って、値をスクレイピングすることになります。

そのようなページで開発者ツールのネットワークをみれば、JSONなどのデータを読み込んでいることがわかります。例えば、下記のUNIQLOのECサイトでは、金額ではありませんが、サイトの一部の情報をAPI経由で呼び出して表示していることがわかります。

一見面倒くさそうに見えますが、このような仕組みのサイトは大抵JSONから値を取得しています。JSONであれば値も取得しやすいので、面倒くさいこともありません。ライブラリのJSONを使えば簡単に値を取り出せます。リクエストを送って返ってきたのが下記のようなJSONだったとします。

JSONとして扱うために、loads()で読み込みます。

JSONから値を取り出すには、キーを指定すればよいので、幾つか試しに値を取得するとこうなります。

実際のScrapyのコードでは、JSONを受け取る前の段階で、商品コードなどをスクレイピングして、リクエスト用のURLを作って、それに対してリクエストを送ることでJSONを取得します。そこから、必要であればdecode()でバイト列の内容をデコードしてJSONに変換し、キーを指定して、値をスクレイピングすることになります。

最終更新

役に立ちましたか?