一.分布式爬蟲簡介
1.介紹:
分布式爬蟲就是多台計算機上都安裝爬蟲程序,重點是聯合采集。比如爬蟲A,B,C分別在三台服務器上,需要一個狀態管理器集中分配,去重這三個爬蟲的url,狀態管理器也是一個服務,需要部署在某一個服務器上。
2.優點:
(1)充分利用多機器的帶寬加速爬取;
(2)充分利用多機器的ip加速爬取速度
3.分布式需要解決的問題:
(1)request隊列集中處理
(2)去重集中處理
二.Redis的簡單使用
1.Redis的數據類型:
1.1(String)字符串:
鍵值對應
1.2(Hash)哈希:
設置多個鍵值對每個 hash 可以存儲 232 -1 鍵值對(40多億)
1.3(List)列表:
左邊添加,右邊添加,左邊取前四個數據
1.4(Set)集合:
添加一個字符串到set()集合,成功返回1,如果已經存在則返回0,最大的成員數為 232 - 1
1.5(zset)有序集合:
添加元素到集合,不同的是每個元素都會關聯一個double類型的分數,通過分數排序。
2.常用命令:
可參考:http://www.runoob.com/redis/redis-sets.html
三.scrapy-redis搭建分布式爬蟲
1.github源碼地址:
https://github.com/rmax/scrapy-redis
2.將scrapy-redis項目clone下到本地,需要src下的scrapy-redis文件:
導入scrapy-redis並安裝redis(pip install redis)設置:

1 #在redis中啟用調度存儲請求隊列。 2 SCHEDULER = “ scrapy_redis.scheduler.Scheduler ” 3 4 #確保所有蜘蛛通過redis共享相同的重復過濾器。 5 DUPEFILTER_CLASS = “ scrapy_redis.dupefilter.RFPDupeFilter ” 6 7 #默認請求序列化程序是pickle,但它可以更改為 8 具有加載和轉儲功能的任何模塊#。請注意, 9 # python版本 10 之間的pickle不兼容。#警告:在蟒蛇3.x中,串行器必須返回字符串鍵和支持 11 #字節的值。由於這個原因,json或msgpack模塊 12 默認不會#工作。在python 2.x中沒有這樣的問題,您可以使用 13 # 'json'或'msgpack'作為序列化程序。 14 # SCHEDULER_SERIALIZER = “scrapy_redis.picklecompat” 15 16 #不要清理redis隊列,允許暫停/恢復抓取。 17 # SCHEDULER_PERSIST =真 18 19 #使用優先級隊列安排請求。(默認) 20 # SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue' 21 22 #替代隊列。 23 # SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue' 24 # SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue' 25 26 #最大空閑時間,防止蜘蛛在分布式爬網時被關閉。 27 #這僅在隊列類為SpiderQueue或SpiderStack時才有效, 28 #也可能在您的蜘蛛第一次啟動時阻塞同一時間(因為隊列為空)。 29 # SCHEDULER_IDLE_BEFORE_CLOSE = 10 30 31 #將已刪除的項目存儲在redis中進行后期處理。 32 ITEM_PIPELINES = { 33 ' scrapy_redis.pipelines.RedisPipeline ': 300 34 } 35 36 #項目管道序列化並存儲此redis密鑰中的項目。 37 # REDIS_ITEMS_KEY ='%(蜘蛛)S:項的 38 39 #項目序列化程序默認為ScrapyJSONEncoder。你可以使用任何 40 #導入的路徑,一個可調用對象。 41 # REDIS_ITEMS_SERIALIZER = 'json.dumps' 42 43 #指定連接到Redis時使用的主機和端口(可選)。 44 # REDIS_HOST = '本地主機' 45 # REDIS_PORT = 6379 46 47 #指定用於連接的完整Redis URL(可選)。 48 #如果設置,則優先於REDIS_HOST和REDIS_PORT設置。 49 # REDIS_URL = 'redis的://用戶:通過@主機名:9001' 50 51 #定制redis的客戶參數(即:套接字超時等) 52 # REDIS_PARAMS = {} 53 #使用自定義redis的客戶端類。 54 # REDIS_PARAMS [ 'redis_cls'] = 'myproject.RedisClient' 55 56 #如果為True,則使用redis'``SPOP``操作。您必須使用``SADD`` 57 #命令將URL添加到redis隊列。如果你這可能是有用的 58 #要避免在開始的URL列表和重復的順序 59 #處理無關緊要。 60 # REDIS_START_URLS_AS_SET =假 61 62 #默認啟動網址RedisSpider和RedisCrawlSpider關鍵。 63 # REDIS_START_URLS_KEY = '%(名)S:start_urls' 64 65 #使用除utf-8之外的其他編碼進行redis。 66 # REDIS_ENCODING = 'latin1的'
3.配置setting:
# SCHEDULER覆蓋原有的,在redis中啟用調度存儲請求隊列 SCHEDULER = "scrapy_redis.scheduler.Scheduler" # 確保所有spider通過redis共享相同的重復過濾器 DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter" # 配置以便后期插入數據庫等操作 ITEM_PIPELINES = { "scrapy_redis.pipelines.RedisPipeline": 300, }
監聽,取不到url不會退出,telnet一直監聽
4.將網址推送到redis,運行lpush myspider:start_urls 起始url:
不設定redis_key,默認為spider:start_urls:
如:lpush jobbole:start_urls http://blog.jobbole.com/all-posts
5.scrapy-redis源碼介紹:
5.1collection.py:
get_redis_from_settings():將所有配置放到dict:params中,用於實例化redis對象。
get_redis():實例化redis對象,from_url方法優先。
5.2defaults.py:
設定默認連接參數。
5.3dupefilter.py(去重類,和scrapy的dupefilter.py幾乎一模一樣):
clear(self):清除request_fingerprint記錄
close(self,reason):結束爬蟲爬取時,調用
from_crawler(cls,crawler):類方法,調用from_settings方法初始化
from_settings(cls,settings):類方法初始化,預留鈎子
log(self,request,spider):根據傳入的debug或者默認顯示log
request_fingerprint(self,request):根據請求信息返回經過sha1計算后的值
request_seen(self,request)調用request_fingerprint,判斷是否訪問過
5.4picklecompat.py:
process_item():調用_process_item。
_process_item():通過rpush方法放到redis的列表里。
5.6queue.py:使用redis制作的隊列,有Fifo(先進先出)、Lifo(后進先出)、PriorityQueue(有序集合取第一個)三種
5.7scheduler.py(調度器類):
enqueue_request():不是白名單且訪問過的,往隊列里放Request對象
next_request():從隊列里取值
5.8spiders.py:爬蟲類
5.9utils.py:
bytes_to_str():字節轉成字符串,默認utf-8