1. 分布式爬蟲(chóng)簡(jiǎn)介
1.1. 分布式系統(tǒng)介紹
- 分布式概念
-- 分布式系統(tǒng)是由一組多臺(tái)計(jì)算機(jī)組成的系統(tǒng)嫉你;
-- 計(jì)算機(jī)之間通過(guò)網(wǎng)絡(luò)進(jìn)行通信;
-- 計(jì)算機(jī)之間為完成共同的任務(wù)而協(xié)調(diào)工作搅荞;
-- 分布式系統(tǒng)的目的是為了利用更多的機(jī)器红氯,處理更多的數(shù)據(jù),完成更多的任務(wù)咕痛; - 分布式系統(tǒng)的實(shí)現(xiàn)
-- 分布式系統(tǒng)的實(shí)現(xiàn)包括 MapReduce 和 Replication痢甘;
-- MapReduce:分布式系統(tǒng)實(shí)現(xiàn)的核心思想,是分片(partition)茉贡,每個(gè)節(jié)點(diǎn)(node)處理一部分任務(wù)塞栅,最后將結(jié)果匯總,該思路即 MapReduce腔丧;
-- Replication:在實(shí)踐中放椰,分布式系統(tǒng)會(huì)遇到斷網(wǎng)作烟、高延遲、單節(jié)點(diǎn)故障等情況砾医,需要系統(tǒng)具有高容錯(cuò)能力拿撩,常用的解決辦法是冗余(replication),即多節(jié)點(diǎn)負(fù)責(zé)同一任務(wù)如蚜,常見(jiàn)于分布式存儲(chǔ)压恒,該思路即 Replication; - 分布式系統(tǒng)需要解決的問(wèn)題
-- 機(jī)器 & 網(wǎng)絡(luò) 異構(gòu)错邦;
-- 節(jié)點(diǎn)故障監(jiān)控探赫;
-- 網(wǎng)絡(luò)丟包、延時(shí)兴猩、亂序等期吓;
關(guān)于分布式系統(tǒng),詳情請(qǐng)參考鏈接:
《什么是分布式系統(tǒng)倾芝,如何學(xué)習(xí)分布式系統(tǒng)》
https://www.cnblogs.com/xybaby/p/7787034.html
1.2. 分布式爬蟲(chóng)介紹
1.2.1. 分布式爬蟲(chóng)分類
-
主從式爬蟲(chóng)
-- 整個(gè)分布式爬蟲(chóng)系統(tǒng)由兩部分組成:master控制節(jié)點(diǎn)和slave爬蟲(chóng)節(jié)點(diǎn)讨勤;
-- master控制節(jié)點(diǎn):負(fù)責(zé)管理所有slave,包括 slave 連接晨另、任務(wù)調(diào)度潭千、分發(fā),維護(hù)爬取隊(duì)列借尿、 收取 salve 上傳的數(shù)據(jù)刨晴,存儲(chǔ)目標(biāo)數(shù)據(jù),新 URL 鏈接去重路翻,新任務(wù)添加等狈癞、結(jié)果回收、匯總茂契;
-- slave爬蟲(chóng)節(jié)點(diǎn)負(fù)責(zé): 從 master 領(lǐng)取任務(wù)蝶桶,并獨(dú)自完成、本節(jié)點(diǎn)爬蟲(chóng)調(diào)度掉冶、數(shù)據(jù)抓取真竖、HTML下載管理、數(shù)據(jù)處理厌小、內(nèi)容解析(解析包括目標(biāo)數(shù)據(jù)和新的URL鏈接)恢共、數(shù)據(jù)存儲(chǔ)、上傳結(jié)果璧亚;
注意:
- 主從模式下 slave 節(jié)點(diǎn)不需要與其他 slave 節(jié)點(diǎn)交流讨韭;
- 主從模式下,負(fù)載瓶頸在服務(wù)器端,主服務(wù)器不做爬取透硝;
-- 主從式爬蟲(chóng)架構(gòu)如下圖:
- 對(duì)等式爬蟲(chóng)
-- 對(duì)等式爬蟲(chóng)模式下吉嚣,所有節(jié)點(diǎn)工作任務(wù)相同;
-- 這是為了解決控制節(jié)點(diǎn)作為爬蟲(chóng)系統(tǒng)核心帶來(lái)的瓶頸問(wèn)題而設(shè)計(jì)的蹬铺;
-- 這種模式一般用于超大規(guī)模爬蟲(chóng)如搜索引擎尝哆,此處不做贅述;
1.2.2. 分布式爬蟲(chóng)的優(yōu)勢(shì)
- 解決目標(biāo)地址對(duì)IP訪問(wèn)頻率的限制的問(wèn)題甜攀;
- 利用更高的帶寬秋泄,提高下載速度;
- 大規(guī)模系統(tǒng)的分布式存儲(chǔ)和備份规阀;
- 系統(tǒng)可擴(kuò)展性恒序;
1.2.3 分布式爬蟲(chóng)需要解決的問(wèn)題
- request 隊(duì)列管理;
- 爬蟲(chóng)的集中去重谁撼;
- 爬取數(shù)據(jù)的統(tǒng)一存儲(chǔ)歧胁;
關(guān)于分布式爬蟲(chóng),詳情請(qǐng)參考:
《簡(jiǎn)單分布式爬蟲(chóng)——第一彈:了解分布式爬蟲(chóng)結(jié)構(gòu)》http://www.reibang.com/p/d148ccc3e50a
《網(wǎng)絡(luò)爬蟲(chóng) | 你知道分布式爬蟲(chóng)是如何工作的嗎厉碟?》http://www.reibang.com/p/6e3eb50fe2b8
2. Scrapy-redis 介紹
2.1. scrapy-redis 簡(jiǎn)介
- scrapy 相關(guān)介紹此處不再贅述喊巍,詳情參考:http://www.scrapyd.cn/;
- scrapy-redis是一個(gè)基于 redis 的 scrapy 插件箍鼓;
- 使用 Redis 數(shù)據(jù)庫(kù)寫(xiě)入崭参、存放和讀取 URL 待爬取隊(duì)列;
- 通過(guò)它可以快速實(shí)現(xiàn)簡(jiǎn)單分布式爬蟲(chóng)程序款咖,
- 該組件本質(zhì)上提供了三大功能:
-- scheduler 調(diào)度器何暮;
-- dupefilter URL去重;
-- pipeline 數(shù)據(jù)持久化铐殃; -
scrapy-redis 架構(gòu)圖:
2.2. Redis 數(shù)據(jù)庫(kù)在 scrapy_redis 中的作用
- 存請(qǐng)求隊(duì)列
- 存指紋
-- 當(dāng)請(qǐng)求到達(dá) Redis 之后海洼,先和之前的請(qǐng)求做指紋比對(duì),如果指紋已存在則丟棄富腊,否則存儲(chǔ)請(qǐng)求坏逢; - 分布式爬蟲(chóng)中,所有的爬蟲(chóng) spider 共享 Redis 隊(duì)列和指紋蟹肘。
2.3. scrapy_redis 與 scrapy 的區(qū)別
- 增加了 Redis 數(shù)據(jù)庫(kù)词疼;
- 隊(duì)列:
-- scrapy 本身不支持爬蟲(chóng) request 隊(duì)列共享俯树,即一個(gè)隊(duì)列只能服務(wù)于一個(gè)爬蟲(chóng)帘腹,不支持分布式爬取许饿;
-- scrapy-redis 則把 request 隊(duì)列存放于 Redis 數(shù)據(jù)庫(kù)阳欲,多個(gè)爬蟲(chóng) spider 可以到同一個(gè) Redis 數(shù)據(jù)庫(kù)里讀取; - 去重:
-- scrapy 使用 set 集合實(shí)現(xiàn) request 去重球化,通過(guò)將 request 與 set 中的已有 request 進(jìn)行比對(duì)秽晚,如果已存在則丟棄;
-- scrapy-redis 使用 Dupelication Filter 組件實(shí)現(xiàn)去重筒愚,scrapy-redis 調(diào)度器從引擎接受 request 并判斷是否重復(fù)赴蝇,并將不重復(fù)的 reuquest 寫(xiě)入 Redis 中的 隊(duì)列,之后調(diào)度器從隊(duì)列中根據(jù)優(yōu)先級(jí) pop 出一個(gè) reuqest 發(fā)送給爬蟲(chóng)引擎 spider 進(jìn)行處理巢掺;
2.4.scrapy-redis 優(yōu)點(diǎn)
- 速度快
-- Redis 數(shù)據(jù)庫(kù)是 key-value 型內(nèi)存數(shù)據(jù)庫(kù)句伶,運(yùn)行速度快,效率高陆淀; - 用法簡(jiǎn)單
-- scrapy-redis 是已經(jīng)造好的輪子考余,拿來(lái)就可以用; - 去重簡(jiǎn)單
-- 使用 Redis 中的 set 類型就可以實(shí)現(xiàn)轧苫;
2.5. scrapy_redis 缺點(diǎn)
- Redis 比較吃內(nèi)存楚堤;
- usage 需要處理;
參考鏈接:
《scrapy-redis 和 scrapy 有什么區(qū)別含懊?》
https://www.zhihu.com/question/32302268/answer/55724369
3. scrapy-redis 的基本使用
3.1. 安裝 scrapy-redis 模塊
- 安裝 scrapy
pip3 install scrapy
- 安裝 scrapy-redis
pip3 install scrapy-redis
3.2. 安裝 Redis 數(shù)據(jù)庫(kù)并配置
- 安裝 Redis
pip3 install redis
- 配置 Redis
vim /usr/local/etc/redis.conf
進(jìn)入 vim 編輯器頁(yè)面后身冬,注釋掉 bind 127.0.0.1。
# bind 127.0.0.1 # 如果不注釋掉岔乔,則只能在本機(jī)上訪問(wèn) Redis 數(shù)據(jù)庫(kù)
3.3. 創(chuàng)建并編寫(xiě)爬蟲(chóng)
- 創(chuàng)建項(xiàng)目
scrapy startproject tutorial # 創(chuàng)建爬蟲(chóng)項(xiàng)目 tutorial
- 編寫(xiě)爬蟲(chóng)
備注:由于本文內(nèi)容并非介紹 scrapy 用法吏恭,所以此處不再贅述
3.4. 修改爬蟲(chóng)項(xiàng)目文件
- 修改 spider.py
from scrapy_redis.spiders import RedisSpider
class TutorialSpider(RedisSpider): # 將爬蟲(chóng)的父類已經(jīng)改成RedisSpider
name = "tutorialspider"
redis_key = 'tutorialspider:start_urls' # 添加的redis_key實(shí)際上是一個(gè)變量名,
# 之后爬蟲(chóng)爬到的所有URL都會(huì)保存到Redis中
# 這個(gè)名為“tutorialspiderspider:start_urls”
# 的列表下面重罪,爬蟲(chóng)同時(shí)也會(huì)從這個(gè)列表中
# 讀取后續(xù)頁(yè)面的URL樱哼。
- 修改 pipeline
此處主要是修改 mysql 數(shù)據(jù)庫(kù)連接,以保證所有數(shù)據(jù)都會(huì)保存于master 的 mysql 數(shù)據(jù)庫(kù)剿配,此處不做贅述搅幅;
master 上 mysql 的 host 為 127.0.0.1
slave 上 mysql 的 host 為 master 的 ip
- 修改 settings.py
-- 替換 SHCEDULER,使用 scrapy_redis 進(jìn)行任務(wù)分發(fā)與調(diào)度
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
-- 使用 scrapy_redis 去重隊(duì)列
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
-- 不清理爬蟲(chóng)隊(duì)列
SCHEDULER_PERSIST = True
注意:
如果這一項(xiàng)為 True呼胚,那么在 Redis 中的 URL 不會(huì)被 Scrapy_redis 清理掉茄唐。
-- 這樣的好處是:爬蟲(chóng)停止了再重新啟動(dòng),它會(huì)從上次暫停的地方開(kāi)始繼續(xù)爬扔沪编;
-- 但是它的弊端也很明顯,如果有多個(gè)爬蟲(chóng)都要從這里讀取 URL年扩,需要另外寫(xiě)一段代碼來(lái)防止重復(fù)爬取蚁廓;如果設(shè)置成了 False,那么 Scrapy_redis 每一次讀取了 URL 以后厨幻,就會(huì)把這個(gè) URL 給刪除相嵌。
-- 這樣的好處是:多個(gè)服務(wù)器的爬蟲(chóng)不會(huì)拿到同一個(gè) URL腿时,也就不會(huì)重復(fù)爬取。
-- 但弊端是:爬蟲(chóng)暫停以后再重新啟動(dòng)饭宾,它會(huì)重新開(kāi)始爬批糟。
-- 爬蟲(chóng)請(qǐng)求調(diào)度算法
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderQueue' # 使用隊(duì)列進(jìn)行調(diào)度
注意:
-- 使用 ‘隊(duì)列’ 進(jìn)行爬蟲(chóng)調(diào)度
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderQueue'-- 使用 ‘棧’ 進(jìn)行爬蟲(chóng)調(diào)度
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderStack'-- 使用 ‘優(yōu)先級(jí)隊(duì)列’ 進(jìn)行爬蟲(chóng)調(diào)度
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.SpiderPriorityQueue'
-- 設(shè)置 Redis 地址和端口
REDIS_HOST = '127.0.0.1' # 修改為Redis的實(shí)際IP地址
REDIS_PORT = 6379 # 修改為Redis的實(shí)際端口
注意:
如果不設(shè)置 Redis 的地址和端口看铆,系統(tǒng)會(huì)默認(rèn) Redis 運(yùn)行在本機(jī)徽鼎。
這樣,就初步實(shí)現(xiàn)了 scrapy-redis 基本的爬蟲(chóng)框架弹惦。