ScrapyでRedisを使う際にscrapy-redisというライブラリがあります。
・scrapy-redis
https://github.com/rmax/scrapy-redis
スケジューラ(起動・入力)やパイプライン(出力)でRedisを利用できるので、フロー的な業務に適した作りになっています。
それぞれ別の機能ですので、パイプラインだけ分けるなどといったことも可能です。
スケジューラーとしてのキューをコントロールできるので、クローラーを途中停止したり規模化をはかったりなどにも向いているようです。
ただ、ドキュメントが少なく日本語での設定ドキュメントが少ないので利用が若干大変が試してみます。
scrapy-redisを試してみる
Scrapyとredisのインストールは以下で実施します。
★CentOS環境の python3.6(pyenv環境)で Scrapy を利用してみる(Scrapy その1)
https://colabmix.co.jp/tech-blog/centos-python3-6-scrapy-install/
★CentOS7系の最新版のredisをyumでインストール
https://colabmix.co.jp/tech-blog/centos7-redis-install/
上記の記事の「sample_crawler」というプロジェクトで実施しまします。
まず、インストールを実施します。
1 2 3 |
$ pip install scrapy_redis |
こちらで準備が完了です。
最初にredisのキューの状況を確認してみます。
1 2 3 4 5 |
$ redis-cli 127.0.0.1:6379> keys * (empty list or set) |
何もないですね。
さて、それでは設定です。
「settings.py」に以下の記述を追加します。
1 2 3 4 |
SCHEDULER = "scrapy_redis.scheduler.Scheduler" DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" |
そして、spiderの設定です。
上記記事の「spiders/devcolla.py」を編集します。
「Spider」関連のクラスの読み込みを変更しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
# -*- coding: utf-8 -*- from sample_crawler.items import SampleCrawlerItem from scrapy_redis.spiders import RedisSpider class DevcollaSpider(RedisSpider): name = 'devcolla' def parse(self, response): for quote in response.css('article.post-list'): item = SampleCrawlerItem() item['title'] = quote.css('h1.entry-title::text').extract_first() item['url'] = quote.css('a::attr(href)').extract_first() yield item |
itemsなども読み込んでいますので、そちらもご確認ください。
それでは起動を行います。
特に出力の設定は行いません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$ scrapy crawl devcolla 2019-03-26 10:53:55 [scrapy.utils.log] INFO: Scrapy 1.5.2 started (bot: sample_crawler) 2019-03-26 10:53:55 [scrapy.utils.log] INFO: Versions: lxml 4.2.1.0, libxml2 2.9.8, cssselect 1.0.3, parsel 1.4.0, w3lib 1.19.0, Twisted 16.2.0, Python 3.6.7 (default, Dec 5 2018, 15:02:05) - [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)], pyOpenSSL 19.0.0 (OpenSSL 1.1.0i 14 Aug 2018), cryptography 2.3.1, Platform Linux-3.10.0-957.10.1.el7.x86_64-x86_64-with-centos-7.6.1810-Core 2019-03-26 10:53:55 [scrapy.crawler] INFO: Overridden settings: {'BOT_NAME': 'sample_crawler', 'DUPEFILTER_CLASS': 'scrapy_redis.dupefilter.RFPDupeFilter', 'NEWSPIDER_MODULE': 'sample_crawler.spiders', 'ROBOTSTXT_OBEY': True, 'SCHEDULER': 'scrapy_redis.scheduler.Scheduler', 'SPIDER_MODULES': ['sample_crawler.spiders']} 2019-03-26 10:53:55 [scrapy.middleware] INFO: Enabled extensions: ['scrapy.extensions.corestats.CoreStats', 'scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats'] 2019-03-26 10:53:55 [devcolla] INFO: Reading start URLs from redis key 'devcolla:start_urls' (batch size: 16, encoding: utf-8 2019-03-26 10:53:55 [scrapy.middleware] INFO: Enabled downloader middlewares: ['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', '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.cookies.CookiesMiddleware', 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware', 'scrapy.downloadermiddlewares.stats.DownloaderStats'] 2019-03-26 10:53:55 [scrapy.middleware] INFO: Enabled spider middlewares: ['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 'scrapy.spidermiddlewares.referer.RefererMiddleware', 'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 'scrapy.spidermiddlewares.depth.DepthMiddleware'] 2019-03-26 10:53:55 [scrapy.middleware] INFO: Enabled item pipelines: [] 2019-03-26 10:53:55 [scrapy.core.engine] INFO: Spider opened 2019-03-26 10:53:56 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) |
この状態でscrapyのプロセスが起動したままになります。
「INFO: Reading start URLs from redis key 'devcolla:start_urls' (batch size: 16, encoding: utf-8」の行にあるように、「devcolla:start_urls」というキーがredisのキューに入るまで待機を行っててくれます。
さて、ここでredisにキューを追加してみます。
以下のようにspider名をつけたキューの「start_urls」を読み込んでくれます。
1 2 3 |
$ redis-cli lpush devcolla:start_urls http://developer-collaboration.com/ |
上記のようにキューを実施すると、待機中のプロセスで以下の表示が行われます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
2019-03-26 10:55:41 [devcolla] DEBUG: Read 1 requests from 'devcolla:start_urls' 2019-03-26 10:55:42 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://developer-collaboration.com/robots.txt> (referer: None) 2019-03-26 10:55:45 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://developer-collaboration.com/> (referer: None) 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'Elasticsearchの形態素解析機Sudachiでユーザー辞書(dictionary)の活用', 'url': 'https://developer-collaboration.com/2019/01/30/elasticsearch-sudachi-user-dictionary/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'Elasticsearchのkuromojiの検索で重要な辞書(dictionary)と類義語(synonym)の設定', 'url': 'https://developer-collaboration.com/2019/01/30/elasticsearch-kuro-dictionary-synonym/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'CentOS7のPython3でMeCabのmecab-ipadic-neologdのインストールと利用', 'url': 'https://developer-collaboration.com/2019/01/30/centos7-python3-mecab-ipadic-neologd/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'CentOS7のPython3でJUMAN++のインストールと利用', 'url': 'https://developer-collaboration.com/2019/01/29/centos7-python3-juman/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'Elasticsearchでエイリアスの作成', 'url': 'https://developer-collaboration.com/2019/01/29/elasticsearch-aliases/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'CentOS7系の最新版のredisをyumでインストール', 'url': 'https://developer-collaboration.com/2018/12/20/centos7-redis-install/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'SumEvalというPythonのテキスト評価用のライブラリを試してみた', 'url': 'https://developer-collaboration.com/2018/12/20/sumeval-python/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'pythonを使ってmongodbの操作', 'url': 'https://developer-collaboration.com/2018/12/18/python-mongodb1/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'Scrapyでデータの保存をmongodbにして見る(Scrapy その4)', 'url': 'https://developer-collaboration.com/2018/12/16/scrapy-mongodb4/'} 2019-03-26 10:55:45 [scrapy.core.scraper] DEBUG: Scraped from <200 http://developer-collaboration.com/> {'title': 'CentOS7系でmongodb4.0のインストール', 'url': 'https://developer-collaboration.com/2018/12/15/centos7-mongodb4-0-install/'} 2019-03-26 10:55:56 [scrapy.extensions.logstats] INFO: Crawled 2 pages (at 2 pages/min), scraped 10 items (at 10 items/min) |
自動的に読み込みを行ってくれました。
こちらで基本的な動作は完了です。
最後にredisの状態を確認してみます。
1 2 3 4 5 |
$ redis-cli 127.0.0.1:6379> keys * (empty list or set) |
キューはredisからは削除されているので、実施ジョブの整理などは特にいらないようですね。
今回はこの辺で。
★関連記事
・scrapy-redisを使って、redisを使ったクローリングを試してみる その2
・scrapy-redisを使って、redisを使ったクローリングを試してみる その3(パラメーターを利用してのクローリング:use parameter)
このブログは株式会社CoLabMixによる技術ブログです。
GCP、AWSなどでのインフラ構築・運用や、クローリング・分析・検索などを主体とした開発を行なっています。
Ruby on RailsやDjango、Pythonなどの開発依頼などお気軽にお声がけください。
開発パートナーを増やしたいという企業と積極的に繋がっていきたいです。