1. 背景
Scrapy 是一個(gè)通用的爬蟲框架,但是不支持分布式,Scrapy-redis是為了更方便地實(shí)現(xiàn)Scrapy分布式爬取,而提供了一些以redis為基礎(chǔ)的組件(僅有組件)。
2. 環(huán)境
- 系統(tǒng):win7
- scrapy-redis
- redis 3.0.5
- python 3.6.1
3. 原理
3.1. 對比一下scrapy 和 Scrapy-redis 的架構(gòu)圖。
scrapy架構(gòu)圖:
scrapy-redis 架構(gòu)圖:
多了一個(gè)redis組件,主要影響兩個(gè)地方:第一個(gè)是調(diào)度器。第二個(gè)是數(shù)據(jù)的處理。 3.2. Scrapy-Redis分布式策略。
作為一個(gè)分布式爬蟲,是需要有一個(gè)Master端(核心服務(wù)器)的,在Master端,會搭建一個(gè)Redis數(shù)據(jù)庫,用來存儲start_urls、request、items。Master的職責(zé)是負(fù)責(zé)url指紋判重,Request的分配,以及數(shù)據(jù)的存儲(一般在Master端會安裝一個(gè)mongodb用來存儲redis中的items)。出了Master之外,還有一個(gè)角色就是slaver(爬蟲程序執(zhí)行端),它主要負(fù)責(zé)執(zhí)行爬蟲程序爬取數(shù)據(jù),并將爬取過程中新的Request提交到Master的redis數(shù)據(jù)庫中。
如上圖,假設(shè)我們有四臺電腦:A, B, C, D ,其中任意一臺電腦都可以作為 Master端 或 Slaver端。整個(gè)流程是:
- 首先Slaver端從Master端拿任務(wù)(Request、url)進(jìn)行數(shù)據(jù)抓取,Slaver抓取數(shù)據(jù)的同時(shí),產(chǎn)生新任務(wù)的Request便提交給 Master 處理;
- Master端只有一個(gè)Redis數(shù)據(jù)庫,負(fù)責(zé)將未處理的Request去重和任務(wù)分配,將處理后的Request加入待爬隊(duì)列,并且存儲爬取的數(shù)據(jù)。
Scrapy-Redis默認(rèn)使用的就是這種策略,我們實(shí)現(xiàn)起來很簡單,因?yàn)槿蝿?wù)調(diào)度等工作Scrapy-Redis都已經(jīng)幫我們做好了,我們只需要繼承RedisSpider、指定redis_key就行了。
缺點(diǎn)是,Scrapy-Redis調(diào)度的任務(wù)是Request對象,里面信息量比較大(不僅包含url,還有callback函數(shù)、headers等信息),可能導(dǎo)致的結(jié)果就是會降低爬蟲速度、而且會占用Redis大量的存儲空間,所以如果要保證效率,那么就需要一定硬件水平。
4. 運(yùn)行流程
第一步:在slaver端的爬蟲中,指定好 redis_key,并指定好redis數(shù)據(jù)庫的地址,比如:
class MySpider(RedisSpider): """Spider that reads urls from redis queue (myspider:start_urls).""" name = "amazon" redis_key = "amazonCategory:start_
# 指定redis數(shù)據(jù)庫的連接參數(shù) "REDIS_HOST": "172.16.1.99", "REDIS_PORT": 6379,
第二步:啟動slaver端的爬蟲,爬蟲進(jìn)入等待狀態(tài),等待 redis 中出現(xiàn) redis_key ,Log如下:
2017-12-12 15:54:18 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot) 2017-12-12 15:54:18 [scrapy.utils.log] INFO: Overridden settings: {"SPIDER_LOADER_WARN_ONLY": True} 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled extensions: ["scrapy.extensions.corestats.CoreStats", "scrapy.extensions.telnet.TelnetConsole", "scrapy.extensions.logstats.LogStats"] 2017-12-12 15:54:18 [myspider_redis] INFO: Reading start URLs from redis key "myspider:start_urls" (batch size: 110, encoding: utf-8 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled downloader middlewares: ["scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware", "scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware", "scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware", "redisClawerSlaver.middlewares.ProxiesMiddleware", "redisClawerSlaver.middlewares.HeadersMiddleware", "scrapy.downloadermiddlewares.retry.RetryMiddleware", "scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware", "scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware", "scrapy.downloadermiddlewares.redirect.RedirectMiddleware", "scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware", "scrapy.downloadermiddlewares.stats.DownloaderStats"] 2017-12-12 15:54:18 [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"] 2017-12-12 15:54:18 [scrapy.middleware] INFO: Enabled item pipelines: ["redisClawerSlaver.pipelines.ExamplePipeline", "scrapy_redis.pipelines.RedisPipeline"] 2017-12-12 15:54:18 [scrapy.core.engine] INFO: Spider opened 2017-12-12 15:54:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-12-12 15:55:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2017-12-12 15:56:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
第三步:啟動腳本,往redis數(shù)據(jù)庫中填入redis_key(start_urls)
#!/usr/bin/env python # -*- coding:utf-8 -*- import redis # 將start_url 存儲到redis中的redis_key中,讓爬蟲去爬取 redis_Host = "172.16.1.99" redis_key = "amazonCategory:start_urls" # 創(chuàng)建redis數(shù)據(jù)庫連接 rediscli = redis.Redis(host = redis_Host, port = 6379, db = "0") # 先將redis中的requests全部清空 flushdbRes = rediscli.flushdb() print(f"flushdbRes = {flushdbRes}") rediscli.lpush(redis_key, https://www.baidu.com)
第四步:slaver端的爬蟲開始爬取數(shù)據(jù)。Log如下:
2017-12-12 15:56:18 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) parse url = https://www.baidu.com, status = 200, meta = {"download_timeout": 25.0, "proxy": "http://proxy.abuyun.com:9020", "download_slot": "www.baidu.com", "download_latency": 0.2569999694824219, "depth": 7} parse url = https://www.baidu.com, status = 200, meta = {"download_timeout": 25.0, "proxy": "http://proxy.abuyun.com:9020", "download_slot": "www.baidu.com", "download_latency": 0.8840000629425049, "depth": 8} 2017-12-12 15:57:18 [scrapy.extensions.logstats] INFO: Crawled 2 pages (at 2 pages/min), scraped 1 items (at 1 items/min)
第五步:啟動腳本,將redis中的items,轉(zhuǎn)儲到mongodb中。
這部分代碼,請參照:scrapy-redis分布式爬蟲的搭建過程(代碼篇)
5. 環(huán)境安裝以及代碼編寫
5.1. scrapy-redis環(huán)境安裝
pip install scrapy-redis
代碼位置:后面可以進(jìn)行修改定制。
5.2. scrapy-redis分布式爬蟲編寫
第一步,下載官網(wǎng)的示例代碼,地址:https://github.com/rmax/scrapy-redis (需要安裝過git)
git clone https://github.com/rmax/scrapy-redis.git
官網(wǎng)提供了兩種示例代碼,分別繼承自 Spider + redis 和 CrawlSpider + redis
第二步,根據(jù)官網(wǎng)提供的示例代碼進(jìn)行修改。
到此這篇關(guān)于scrapy-redis分布式爬蟲的搭建過程(理論篇)的文章就介紹到這了,更多相關(guān)scrapy redis分布式爬蟲搭建內(nèi)容請搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!
原文鏈接:https://blog.csdn.net/zwq912318834/article/details/78854571