Scrapy入門②クローリング時に確認必須な最低限の設定と、データ保持クラスItemsの作成

スポンサーリンク

(今回の記事は、Scrapy入門① とりあえずクローラーを作って実行し、Webサイトからデータを取得してみるとこまでの続きです。Scrapyを使うのが初めてで、まだ第一回を見てない方はぜひ初めからチェックしてみてください♪)

今回は、Scrapyを使って「TechCrunch(http://jp.techcrunch.com/)」のサイトから、

  • トップページに表示されている新着記事一覧を取得し、
  • さらに各記事の詳細ページを開き、
  • 詳細記事の本文を取得する

というクローラーを作成します。

やってること自体は前回とさほど変わらないのですが、今回はSpider単体ではなくプロジェクト単位でのクローラー開発を行い、

  • クローリングに関する各種設定(settings.py)
  • データ保持クラス・オブジェクトの活用(Items.py)

など、Scrapyに用意されている様々な便利機能たちの機能の使い方を学んでいきます。

Scrapyプロジェクトの作成

前回はSpiderのみを単体で作りましたが、基本的にScrapyはプロジェクト単位でクローラーを作っていきます。

まずは以下のコマンドで、Scrapyのプロジェクトを作成してみましょう。

$ scrapy startproject tcproject

startprojectコマンドを実行するとScrapyプロジェクトが生成され、以下のようなメッセージが表示されます。

New Scrapy project ‘tcproject’, using template directory
/scrapy/templates/project’, created in:
/your_path/tcproject

You can start your first spider with:
cd tcproject
scrapy genspider example example.com

作成したtcprojectのディレクトリに移動し、ファイル構成を見てみます。

projectのファイル構成を見るのは$ ls -Rとかでもいいんですけど、treeコマンドをbrewかなんかで入れとくと便利です。

$ cd tcproject/
$ tree .
.
├── scrapy.cfg
└── tcproject
├── __init__.py
├── __pycache__
├── items.py
├── middlewares.py
├── pipelines.py
├── settings.py
└── spiders
├── __init__.py
└── __pycache__

役割ごとにいろいろなファイルがありますが、いきなり全部把握しなくても大丈夫なので、順を追って見ていきましょう。

今回の記事で作成するクローラで扱うのは、settings.py, items.py, spider(後で作成)のみです。

settings.py – Scrapyの設定ファイルの記述

Scrapyではクローリング時に必要となる様々な処理があらかじめオプションとして用意されており、設定ファイルに記述を追加するだけで、クローリング間隔の調整やユーザーエージェントの設定、キャッシュや並行処理などに至るまでの様々な機能を、わざわざ自分でコードを書くことなく簡単に利用することができます。

Scrapyの設定は、tcprojectの下にあるsettings.pyというファイルに記述します。

まずは忘れないうちに、クロール先に迷惑をかけないための設定を済ませておきましょう。
settings.pyを適当なエディタで開いて、以下の項目を追加します。

クロール間隔の調整をする

まずは、クロール先のサイトからデータをダウンロードする際の間隔を設定します。

settings.pyの中に、

# DOWNLOAD_DELAY = 3

とコメントアウトされている箇所があるはずですので、この行のコメントを外して設定を有効にします。

数字は秒数(ミリ秒ではない)を表しているので、この場合のクロール間隔は3秒になります。

クロール間隔をミリ秒(ms)で指定したい場合は以下。

DOWNLOAD_DELAY = 1.25

なお、クロールの間隔は1秒以上空けることをお勧めします。

[info] クロール間隔をランダムにする

上記のDOWNLOAD_DELAYと合わせて、

RANDOMIZE_DOWNLOAD_DELAY = True

という項目を設定しておけば、クロール間隔をDOWNLOAD_DELAYで設定した時間の0.5~1.5倍の間でランダムに調整してくれます。
[/info]

robots.txtの指示に従う

次に、クロール先サイトのrobots.txtの指示に従う設定をしておきます。

ROBOTSTXT_OBEY = True

Scrapyのstartprojectコマンドでプロジェクトを作成した場合は初めからTrueになっているはずですが、一応確認しておきましょう。

連絡先の明示

クロール先のサイトの管理者にわかるように、クローラーのユーザーエージェントにメールアドレスなどの連絡先を明記しておくとお行儀がよいです。

連絡がつくようにしておけば、何かあった際にいきなり訴えられたりされずに済むかもしれないので、未然にトラブルの可能性を回避するためにも以下の例を参考に連絡先を設定しておくといいでしょう。

USER_AGENT = “Scrapybot/1.0 (+youremailaddress@example.com)”

jsonで出力した際の日本語がエスケープされないようにする

Scrapyで日本語を含む文字列をjsonに出力すると、文字列がエスケープされてそのままだと読めなくなってしまうので、以下の設定で文字コードを指定しておきましょう。

FEED_EXPORT_ENCODING=’utf-8′

Items.py – データ格納クラスを作成する

Scrapyでは、取得したデータをItemというオブジェクトに格納します。

Itemオブジェクトを利用することで、

  • データの種類をクラスで判別できる
  • あらかじめ定義したフィールドに値を代入するため、間違えなくて済む

などのメリットがあります。

Itemは、Items.pyにクラスとして定義していきます。

Items.pyに保持したいデータのまとまりごとにクラスを定義し、そこで<フィールド名> = scrapy.Field()とすることで、値を保持するフィールドを定義できます。

以下のサンプルでは、取得した記事データを扱うクラスArticleを定義し、その中で

  • 記事タイトルを格納するtitle
  • 記事本文を格納するbody

を定義しています。

Items.pyに定義したデータ保持クラスは、spiderなどでItemオブジュクトとして利用できます。

Itemオブジェクトは、辞書(dict,他の言語でいうmap,hashmapなど連想配列)みたいにキーを指定して要素にアクセスすることができます。

item = Article()
item[‘title’] = ‘breaking: you are fired!’

ただし、Itemsオブジェクトはdictやmapと違い、定義されていないフィールドに値を追加することはできません。

item[‘author’] = ‘John Do’ # authorは定義されていないのでエラー

Itemで定義されていないフィールドにアクセスしようとすると、例外が発生します。

Spiderの作成

次に、Spiderを作っていきます。

前回の記事で紹介した、Scrapyのgenspiderコマンドを使ってSpiderを生成してみましょう。

第1引数にSpiderの名前、第2引数にクロール対象のドメインを指定してgenspiderコマンドを実行します。

$ scrapy genspider tcspider jp.techcrunch.com

プロジェクトのspidersディレクトリに以下のようなtcspider.pyというファイルができているはずですので確認します。

生成されたコードをベースに、必要な処理を加えていきます。

今回のサンプルで使うSpiderの完成品をまず以下に示しておきます。

サンプルの解説

まずgenspiderで生成されたspiderの一行目、utf−8とか書いているコメント行はPython3でScrapyを使う分には不要なので削除します。

①の箇所では、トップページから個別記事ページへのリンク文字列を抜き出し、1つずつ順番にparse_articlesに渡す処理を行います。

この行では、response.css(‘h2.post-title a::attr(“href”)’).extract()で取得した個別記事のURLのリストから、要素(url)を1つずつ取り出しforループにわたします。

そして②の行で、url(記事詳細ページへのリンクurl)をscrapy.Requestに渡し、レスポンス(記事詳細ページ)を自分自身のparse_articlesで処理します。

parse_articleメソッドでは、記事詳細ページからタイトルと本文を抜き出し、それぞれitemオブジェクトに格納して返します。

これを、トップページに表示されている記事一覧の数だけ繰り返します。

Spiderの実行

作成したSpiderは以下のコマンドで実行できます。

$ scrapy crawl tcspider -o tcarticles.jl

scrapy crawlコマンドに続いて実行するspiderの名前を指定し、
-o オプションで実行結果を保存する先のファイルを指定します。

実行結果の確認は以下のコマンドで。

$ cat tcarticles.jl

どうでしょう?うまくいけば、無事にタイトルと記事本文が取得できているはずです。

なお、記事本文以外にiframeタグの中身とかちょっといらんものも混じってしまうと思いますが、こういうのの処理はreadableとかhtml.parserなどを使えばよろしいかと。また次回にでも。

参考にしたもの

Webスクレイピングのノウハウを公開します
http://tech.respect-pal.jp/web-scraping/

scrapyのJSON出力を日本語にする方法
http://qiita.com/shiozaki/items/689713b4cfb869e7f54c

ABOUTこの記事をかいた人

職業:遊び人。1日の半分は睡眠時間の超ロングスリーパー。元大手IT企業のサラリーマンだったが、ブラックな労働環境で体を壊した挙句クビになり、やむをえず独立。それ以来定職にもつかず、半分遊びのようなヌルい仕事をしながら適当に暮らしている。良く言えばノマドワーカー。 詳しいプロフィールはこちら