29. Scrapy 框架-分布式
scrapy-redis
一個(gè)三方的基于redis的分布式爬蟲(chóng)框架,配合scrapy使用,讓爬蟲(chóng)具有了分布式爬取的功能。
github地址: https://github.com/darkrho/scrapy-redis
2. 分布式原理
scrapy-redis實(shí)現(xiàn)分布式,其實(shí)從原理上來(lái)說(shuō)很簡(jiǎn)單,這里為描述方便,我們把自己的核心服務(wù)器稱為master,而把用于跑爬蟲(chóng)程序的機(jī)器稱為slave
我們知道,采用scrapy框架抓取網(wǎng)頁(yè),我們需要首先給定它一些start_urls,爬蟲(chóng)首先訪問(wèn)start_urls里面的url,再根據(jù)我們的具體邏輯,對(duì)里面的元素、或者是其他的二級(jí)、三級(jí)頁(yè)面進(jìn)行抓取。而要實(shí)現(xiàn)分布式,我們只需要在這個(gè)starts_urls里面做文章就行了
我們?cè)?span id="5tt3ttt3t" class="md-pair-s " style="">master上搭建一個(gè)redis數(shù)據(jù)庫(kù)`(注意這個(gè)數(shù)據(jù)庫(kù)只用作url的存儲(chǔ)),并對(duì)每一個(gè)需要爬取的網(wǎng)站類型,都開(kāi)辟一個(gè)單獨(dú)的列表字段。通過(guò)設(shè)置slave上scrapy-redis獲取url的地址為master地址。這樣的結(jié)果就是,盡管有多個(gè)slave,然而大家獲取url的地方只有一個(gè),那就是服務(wù)器master上的redis數(shù)據(jù)庫(kù)
并且,由于scrapy-redis自身的隊(duì)列機(jī)制,slave獲取的鏈接不會(huì)相互沖突。這樣各個(gè)slave在完成抓取任務(wù)之后,再把獲取的結(jié)果匯總到服務(wù)器上
好處
程序移植性強(qiáng),只要處理好路徑問(wèn)題,把slave上的程序移植到另一臺(tái)機(jī)器上運(yùn)行,基本上就是復(fù)制粘貼的事情
3.分布式爬蟲(chóng)的實(shí)現(xiàn)
使用三臺(tái)機(jī)器,一臺(tái)是win10,兩臺(tái)是centos6,分別在兩臺(tái)機(jī)器上部署scrapy來(lái)進(jìn)行分布式抓取一個(gè)網(wǎng)站
win10的ip地址為192.168.31.245,用來(lái)作為redis的master端,centos的機(jī)器作為slave
master的爬蟲(chóng)運(yùn)行時(shí)會(huì)把提取到的url封裝成request放到redis中的數(shù)據(jù)庫(kù):“dmoz:requests”,并且從該數(shù)據(jù)庫(kù)中提取request后下載網(wǎng)頁(yè),再把網(wǎng)頁(yè)的內(nèi)容存放到redis的另一個(gè)數(shù)據(jù)庫(kù)中“dmoz:items”
slave從master的redis中取出待抓取的request,下載完網(wǎng)頁(yè)之后就把網(wǎng)頁(yè)的內(nèi)容發(fā)送回master的redis
重復(fù)上面的3和4,直到master的redis中的“dmoz:requests”數(shù)據(jù)庫(kù)為空,再把master的redis中的“dmoz:items”數(shù)據(jù)庫(kù)寫入到mongodb中
master里的reids還有一個(gè)數(shù)據(jù)“dmoz:dupefilter”是用來(lái)存儲(chǔ)抓取過(guò)的url的指紋(使用哈希函數(shù)將url運(yùn)算后的結(jié)果),是防止重復(fù)抓取的
4. scrapy-redis框架的安裝
pip install scrapy-redis
5. 部署scrapy-redis
5.1 slave端
在windows上的settings.py文件的最后增加如下一行
REDIS_HOST = 'localhost' #master IP
REDIS_PORT = 6379
配置好了遠(yuǎn)程的redis地址后啟動(dòng)兩個(gè)爬蟲(chóng)(啟動(dòng)爬蟲(chóng)沒(méi)有順序限制)
6 給爬蟲(chóng)增加配置信息
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
SCHEDULER_PERSIST = True
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderPriorityQueue"
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderQueue"
#SCHEDULER_QUEUE_CLASS = "scrapy_redis.queue.SpiderStack"
ITEM_PIPELINES = {
? ?'example.pipelines.ExamplePipeline': 300,
? ?'scrapy_redis.pipelines.RedisPipeline': 400,
}
7 運(yùn)行程序
7.1 運(yùn)行slave
scrapy runspider 文件名.py
開(kāi)起沒(méi)有先后順序
7.2 運(yùn)行master
lpush (redis_key) ?url #括號(hào)不用寫
說(shuō)明
這個(gè)命令是在redis-cli中運(yùn)行
redis_key 是 spider.py文件中的redis_key的值
url 開(kāi)始爬取地址,不加雙引號(hào)
8 數(shù)據(jù)導(dǎo)入到mongodb中
等到爬蟲(chóng)結(jié)束后,如果要把數(shù)據(jù)存儲(chǔ)到mongodb中,就應(yīng)該修改master端process_items.py文件,如下
9 數(shù)據(jù)導(dǎo)入到MySQL中
等到爬蟲(chóng)結(jié)束后,如果要把數(shù)據(jù)存儲(chǔ)到mongodb中,就應(yīng)該修改master端process_items.py文件,如下
