Scrapy入門(3)
はじめに
前回までの記事では、Scrapyを利用してWebAPIをコールする方法を試しました。今回はファイルのダウンロード処理を行うSpiderを作成してみましょう。
Spiderの作成
今回はMLBに関するデータ(zipファイル)をダウンロードするSpiderを作成します。実際のデータはSean Lahman Databaseで公開されているデータを利用します。ダウンロードしたzipファイルは任意のディレクトリに保存することにしましょう。
Spriderの処理の流れは次の通りです。
- start_urlsのページの内容を取得
- 取得したページの内容を解析し、aタグのhrefにcsvの文字列が含まれているurlを取得
- 上記で取得したurlの内容を取得
# -*- coding:utf-8 -*-
from scrapy import Spider
from scrapy.http import Request
class GetCSVSpider(Spider):
name = 'get_csv_spider'
allowed_domains = ['seanlahman.com']
custom_settings = {
'DOWNLOAD_DELAY': 1.5,
}
# CSVファイルを保存する任意のディレクトリ
DIR_NAME = '/tmp/csv/'
# エンドポイント(クローリングを開始するURLを記載する)
start_urls = ['http://seanlahman.com/baseball-archive/statistics/']
# URLの抽出処理を記載
def parse(self, response):
for href in response.css('.entry-content a[href*=csv]::attr(href)'):
full_url = response.urljoin(href.extract())
# 抽出したURLを元にRequestを作成し、ダウンロードする
yield Request(full_url, callback=self.parse_item)
# ダウンロードしたページを元に、内容を抽出し保存する
def parse_item(self, response):
file_name = '{0}{1}'.format(self.DIR_NAME, response.url.split('/')[-1])
# ファイルの保存
f = open(file_name, 'w')
f.write(response.body)
f.close()
実行
Scrapy付属のコマンドを利用してクロールを実行します。
scrapy runspider get_csv_spider
コマンドを実行すると下記のようなログがコンソールに表示されます。ログには取得中のURL、ステータス、バイト数、サマリーなど有益な情報が表示されます。
2016-12-06 10:02:22 [scrapy] INFO: Scrapy 1.2.0 started (bot: scrapybot)
2016-12-06 10:02:22 [scrapy] INFO: Overridden settings: {'TELNETCONSOLE_ENABLED': False, 'SPIDER_MODULES': ['crawler.main.spiders'], 'COOKIES_ENABLED': False, 'DOWNLOAD_DELAY': 1}
2016-12-06 10:02:22 [scrapy] INFO: Enabled extensions:
['scrapy.extensions.logstats.LogStats',
'scrapy.extensions.corestats.CoreStats']
2016-12-06 10:02:22 [scrapy] INFO: Enabled downloader middlewares:
['scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware',
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware',
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware',
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware',
'scrapy.downloadermiddlewares.retry.RetryMiddleware',
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware',
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware',
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware',
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware',
'scrapy.downloadermiddlewares.stats.DownloaderStats']
2016-12-06 10:02:22 [scrapy] INFO: Enabled spider middlewares:
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware',
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware',
'scrapy.spidermiddlewares.referer.RefererMiddleware',
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware',
'scrapy.spidermiddlewares.depth.DepthMiddleware']
2016-12-06 10:02:22 [scrapy] INFO: Enabled item pipelines:
[]
2016-12-06 10:02:22 [scrapy] INFO: Spider opened
2016-12-06 10:02:22 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2016-12-06 10:02:23 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/baseball-archive/statistics/> (referer: None)
2016-12-06 10:02:28 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman30_csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:35 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman51-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:38 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman_50-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:39 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman53_csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:41 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman56-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:41 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman52_csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:42 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman54_csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:47 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman591-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:49 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman55_csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:49 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman57-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:52 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman58-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:55 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman-csv_2014-02-14.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:02:55 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman-csv_2015-01-24.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:03:00 [scrapy] DEBUG: Crawled (200) <GET http://seanlahman.com/files/database/lahman2012-csv.zip> (referer: http://seanlahman.com/baseball-archive/statistics/)
2016-12-06 10:03:00 [scrapy] INFO: Closing spider (finished)
2016-12-06 10:03:00 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 4518,
'downloader/request_count': 15,
'downloader/request_method_count/GET': 15,
'downloader/response_bytes': 104279737,
'downloader/response_count': 15,
'downloader/response_status_count/200': 15,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2016, 12, 6, 1, 3, 0, 285944),
'log_count/DEBUG': 15,
'log_count/INFO': 7,
'request_depth_max': 1,
'response_received_count': 15,
'scheduler/dequeued': 15,
'scheduler/dequeued/memory': 15,
'scheduler/enqueued': 15,
'scheduler/enqueued/memory': 15,
'start_time': datetime.datetime(2016, 12, 6, 1, 2, 22, 878024)}
2016-12-06 10:03:00 [scrapy] INFO: Spider closed (finished)
ダウンロードが完了したので実際にダウンロードされているか確認しましょう。
無事ダウンロードされているようですね。
tree /tmp/csv
/tmp/csv
├── lahman-csv_2014-02-14.zip
├── lahman-csv_2015-01-24.zip
├── lahman2012-csv.zip
├── lahman30_csv.zip
├── lahman51-csv.zip
├── lahman52_csv.zip
├── lahman53_csv.zip
├── lahman54_csv.zip
├── lahman55_csv.zip
├── lahman56-csv.zip
├── lahman57-csv.zip
├── lahman58-csv.zip
├── lahman591-csv.zip
└── lahman_50-csv.zip
0 directories, 14 files
終わりに
Scrapyを使用すると、ファイルのダウンロード処理も簡単に記述することができます。Scrapyはクローリング用のフレームワークなので、開発者はフレームワークから呼び出される部分にのみ集中して開発することが可能です。次回以降は今回説明しなかった、データのパイプライン処理について取り上げます。お楽しみに!