Scrapyを使ってクローリング、スクレイピングをやってみた話

はじめに

普段はJavaを主に利用しているのですが、ちょっとした作業で使うのにはちょっと面倒臭いものです。

今回はあるサイトからデータを取得したいとの相談を受けまして、Pythonにより実装されたクローリング、スクレイピングフレームワークであるScrapyを利用してやってみました。

なお、Spiderクラスのみの最小の構成で動作させているため、Itemクラスは作成していません。

インストール

pip3 install scrapy

プロジェクトの作成

scrapy startproject first_scrapy
New Scrapy project 'first_scrapy', using template directory '/usr/local/lib/python3.6/site-packages/scrapy/templates/project', created in:
    /Users/XXXXX/first_scrapy

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

cd first_scrapy
tree .
.
├── first_scrapy
│   ├── __init__.py
│   ├── __pycache__
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       └── __pycache__
└── scrapy.cfg

4 directories, 7 files

設定の変更

settings.pyにはScrapyの様々なオプションを指定できます。

指定可能なオプションは公式から確認できます。

今回は以下のオプションのみ変更しています。

  • DOWNLOAD_DELAY:1つのページをダウンロードしてから、次のページをダウンロードすするまでの間隔(単位:秒)
  • ROBOTSTXT_OBEY:robots.txtがある場合は、それに従うかどうか
  • FEED_EXPORT_ENCODING:出力ファイルの文字コード
DOWNLOAD_DELAY = 3
ROBOTSTXT_OBEY = True
FEED_EXPORT_ENCODING = 'utf-8'

Spiderの作成

ガイドメッセージに従いSpiderを作成していきます。

Spiderは「scrapy.Spider」のサブクラスで、最初にアクセスするURLと、どのようにHTMLからデータを抽出するかを定義します。

scrapy genspider モジュール名 クローリング対象のドメイン

scrapy genspider example example.com
Created spider 'example' using template 'basic' in module:
  first_scrapy.spiders.example

以下のようなコードが作成されます

# -*- coding: utf-8 -*-
import scrapy


class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com/']

    def parse(self, response):
        pass

start_urlsには最初にアクセスするURLを指定します。

この処理を実行するとstart_urlsにアクセスした結果を引数としてparseメソッドが実行されます。

responseに対して、XPathCSS形式でセレクタを指定することで欲しい情報を取得することが可能となっています。

具体的には以下のイメージです。

    def parse(self, response):
        ids = response.xpath('//div[@class="example"]/@id').extract()
        for id in ids:
            yield {
                "ID" : id
            }
        pass

scrapy runspiderを実行することでSpiderを実行することができます。 以下の例の場合、結果がexample.csvに出力されます。

scrapy runspider --nolog first_scrapy/spiders/example.py -o example.csv

なお、scrapy.Requestをコールすることで次のurlを引き続きスクレイピングさせることが出来ます。

# 同じメソッドでパースさせる場合
yield scrapy.Request(url)

# 別のパースメソッドでパースさせる場合
yield scrapy.Request(url ,callback=self.XXXXX)

トラブルシューティング

インストール時のエラー

Windows環境でpip3にてインストールを行う際に以下のエラーが発生しました。

error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools

2018/06/22現在、エラーのurlではダウンロードできなくなっていますが、microsoftからダウンロードできます。

scrapy runspiderの実行時エラー

scrapy runspiderを実行する際に以下のエラーが発生しました。

ImportError: No module named win32api

公式にもpywin32をインストールするように記載があったので、大人しくインストールしました。

参考