scrapy 實作生成指紋的方法
預設使用sha1加密了請求方法,請求體,和請求url位址,得到16進制字元串
fp = hashlib.sha1()
fp.update(to_bytes(request.method))
fp.update(to_bytes(canonicalize_url(request.url)))
fp.update(request.body or b'')
cache[include_headers] = fp.hexdigest() #指紋
要檢視資料是否存在于redis的集合中,如果不存在就插入
added = self.server.sadd(self.key, fp)
#added= 0 表示存在
#added!=0 表示不存在,并且已經插入
return added == 0
scrapy_redis和scrapy中request入隊的條件
- request對象沒見過,新的request
- dont_filter = True 不過濾的情況下會反複抓取
- start_urls 中的url能夠被反複抓取
?️
scrapy-redis
存放:過濾完存入請求隊列
過濾:set 集合先過濾指紋,指紋就是對每個請求進行轉換,判斷能否存入 redis 集合,集合會自動去重,能存入,說明沒有請求過,就将請求存入到請求隊列中。
多個伺服器調用同一個 redis 伺服器,可以實作分布式爬蟲
指紋預設忽略 header,因為 header 裡面可能存了 cookie,而 cookie 可能不一樣,會導緻生成的指紋不一樣,是以預設忽略
哈希函數的特性
- 輸入域無限,輸出域有限
- 相同的輸入,必然得到相同的輸出(不是随機性)
- 不同的輸入,也可能得到相同的輸出(哈希碰撞)
- 離散性:對于輸出域中的每個結果,在整個輸出域是均勻分布的
dict 字典 -> 哈希表
每個字典過來都需要使用哈希表對 key 進行計算
需要閱讀的書籍
- 作業系統:精髓與設計原理
- 資料結構
- 算法導論
網易公開課 算法導論 書籍視訊
scrapy_redis為什麼能夠實作去重和請求的持久化以及分布式爬蟲
- scrapy_redis把指紋和request對象存儲在了redis,下一次程式啟動起來之後會從之前的redis中讀取資料
- 實作分布式:多個伺服器上的爬蟲公用一個redis
scray_redis中dmoz給我們展示了一個什麼樣的爬蟲
- 增量式的爬蟲:基于request對象的增量
scrapy_redis中如何實作一個增量式的爬蟲
- settings中進行配置,指定去重的類,排程器的類,添加上redis_url
scrapy中如何生成的指紋,有什麼啟發
使用sha1加密請求的url位址,請求的方法和請求體,得到16進制字元串作為指紋
fp = hashlib.sha1()
fp.update(request.url)
fp.update(request.method)
fp.update(request.body or b"")
Redisspider的爬蟲和scrapy.spider的差別
- 差別
- redisspider繼承的父類是RedisSpider
- redisspider沒有start_url,有redis_key
- redis_key表示redis中存放start_url位址的鍵
- 建立爬蟲
- scrapy genspider 爬蟲名 允許爬取的範圍
- 修改父類
- 添加redis_key
- 啟動爬蟲
- 讓爬蟲就緒 scrapy crawl 爬蟲
- lpush redis_key url 爬蟲會啟動
RedisCrawlSpider的爬蟲和crwalspdier的差別
- 差別
- RedisCrawlSpider繼承的父類是RedisCrawlSpider
- RedisCrawlSpider沒有start_url,有redis_key
- redis_key表示redis中存放start_url位址的鍵
- 建立爬蟲
- scrapy genspider -t crwal 爬蟲名 允許爬取的範圍
- 修改父類
- 添加redis_key
- 啟動爬蟲
- 讓爬蟲就緒 scrapy crawl 爬蟲
- lpush redis_key url 爬蟲會啟動