データ分析エンジニアのブログ

日常のことからプログラミングや機械学習まで@六本木

PythonでScrapyを使ってクローリングをしてみる


前回はurllib2というモジュールを使った簡単なスクレイピングの方法を紹介しました。
今日はScrapyというクローリング+スクレイピングフレームワークを使って、
ウェブから情報を取ってくる方法をご紹介します。


フレームワークな分、以前紹介した手法よりも大掛かりなものになるので
クローリング対象の大小によって、使い分けするといいでしょう。

スクレイピングとクローリングの違い

クローリング: Webページをリンクを辿り情報を収集すること
スクレイピング: Webページから意図した情報を抜き出す作業のこと
たまに一緒の意味で使う人がいるのですが、厳密にはこのような定義です。

Scrapyとは

Scrapyはクローリングとスクレイピングの両方のフレームワークです。
robots.txtやsitemapをパースしてくれたり、
クローリングの間隔を一括で定義したりできるので便利です。

インストール方法

pipからインストールできます。

$ sudo pip install Scrapy
前準備

以下のコマンドでプロジェクトのフォルダとファイルが生成されます。

$ scrapy startproject rakutenscrapy

設定ファイルを変更します。

# rakutenscrapy/rakutenscrapy/settings.py
DOWNLOAD_DELAY = 3 # sleep間隔
ROBOTSTXT_OBEY = True # robots.txtに従うかどうか
出力データのファイルを作成

スクレイピングしたデータはデフォルトでJSONline形式で出力されます。
初めて見る形式でしたが、一行毎にJSONがある形式です。
出力されるデータの構造は以下のように設定できます。

# rakutenscrapy/rakutenscrapy/items.py
class RakutenItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    link = scrapy.Field()
クローリングとスクレイピングのプログラムを作成
# coding: utf-8

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector

from rakutenscrapy.items import RakutenItem


class RakutenSpider(CrawlSpider):
    name = 'rakuten'
    allowed_domains = ['http://product.rakuten.co.jp']
    start_urls = [http://product.rakuten.co.jp/503169/]
    rules = [
        # 正規表現にマッチするリンクをクローリング
        Rule(SgmlLinkExtractor(allow=(r'/503169/(.*)', ), restrict_xpaths=('/html', ))),
        # 正規表現にマッチするリンクをparseメソッドでスクレイピング
        Rule(SgmlLinkExtractor(allow=(r'/503169/(.*)', ), restrict_xpaths=('/html', )), callback='parse_news'),
    ]

    def parse(self, response):
        sel = Selector(response)
        match = sel.xpath('//div[@class="proListItemName"]/table')

        for m in match:
            item = RakutenItem()
            item['title'] = m.xpath('.//a/text()').extract()[0]
            item['link'] = m.xpath('.//a/@href').extract()[0]
            yield item
Scrapyの実行

コマンドひとつで実行することができます!

$ scrapy crawl rakuten -o rakuten-item.jl


以上で大規模なクローリングとスクレイピングが楽に実装できます。


urllib2とElementTreeを使う方法に比べると、かなり手間に感じますが、
何回かすると、とても簡単にクローリングできるようになるのでぜひやってみてください。


参考
http://orangain.hatenablog.com/entry/scrapy
http://akiniwa.hatenablog.jp/entry/2013/04/15/001411