Scrapy-Redis是根據隊列排程請求,新添加的排在後面。當隊列的長度排了很長的隊,但是有一種資料我不希望它排隊,我希望它直接請求,但是需要跟隊列用同一Redis去重。
然後研究了一下Scrapy和Scrapy-Redis源碼,實作手動添加指紋功能。
dupefilter.py
打開
scrapy_redis.dupefilter.py
檔案,找到
request_seen()
方法
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsICM0ITMvw1dvwlMvwlM3VWaWV2Zh1WaDdTJwlmc0N3LcRnbllmcv1yb0VXYvwlMyd2bNV2Zh1Wa-cmbw5iNmFDMwUWMxgTYzIWYwQ2YtQjNzAzM1QTMvw1cldWYtl2XkF2bsBXdvw1bp5SdoNnbhlmauMXZnFWbp1CZh9GbwV3Lc9CX6MHc0RHaiojIsJye.png)
在這裡我們注意到同樣實作了一個 request_seen() 方法,和 Scrapy 中的 request_seen() 方法實作極其類似,不過在這裡集合使用的是
server
對象的
sadd()
操作,也就是集合不再是簡單的一個簡單資料結構了,在這裡直接換成了資料庫的存儲方式。
request.py
從上圖
request_seen()
方法中注意到
request_fingerprint()
方法,
request_fingerprint()
是擷取指紋,這裡Scrapy-Redis是直接用的Scrapy的方法。檔案路徑
scrapy.utils.request.py
從源碼可以看到指紋是通過
sha1
加密,需要
request.method
,
request.url
,
request.body
必要的參數。然後傳回指紋。
request_fingerprint.py
知道了指紋添加的原理,接下來開始寫代碼,手動添加添加去重指紋。建立
request_fingerprint.py
檔案
# coding=utf-8
#!/usr/bin python
'''
Author: lifenggang
ZsLfg
Python3 環境
Email: [email protected]
'''
import redis
from scrapy.utils.request import request_fingerprint
class Request_Fingerprint(object):
def __init__(self, url):
self.method = 'GET' # 如果是post請求,請修改成POST
self.url = url
self.body = b''
class Redis_Fingerprint(object):
def __init__(self):
self.key = 'top_bilibili_spider:dupefilter' # 此處修改成對應的資料庫
self.server = redis.Redis(host='192.168.0.157', port=6379, db=0, password=None)
def sadd(self, fp):
added = self.server.sadd(self.key, fp) # 這将傳回添加的值的數量,如果已經存在,則傳回零。
return added
def run(url):
'''
手動添加url指紋,存在傳回True,不存在傳回False
:param url: 傳入需要去重的url
:return: 存在傳回True,不存在傳回False
'''
re = Request_Fingerprint(url=url)
fp = request_fingerprint(re)
rf = Redis_Fingerprint()
added = rf.sadd(fp) # 存在傳回True,不存在傳回False
return added == 0
if __name__ == '__main__':
run('https://api.bilibili.com/x/space/acc/info?mid=466272&jsonp=jsonp')
如果覺得文章對你有幫助,能否幫我留一個贊。