天天看點

Scrapy-Redis手動添加添加去重url(指紋)

Scrapy-Redis是根據隊列排程請求,新添加的排在後面。當隊列的長度排了很長的隊,但是有一種資料我不希望它排隊,我希望它直接請求,但是需要跟隊列用同一Redis去重。

然後研究了一下Scrapy和Scrapy-Redis源碼,實作手動添加指紋功能。

dupefilter.py

打開

scrapy_redis.dupefilter.py

檔案,找到

request_seen()

方法

Scrapy-Redis手動添加添加去重url(指紋)

在這裡我們注意到同樣實作了一個 request_seen() 方法,和 Scrapy 中的 request_seen() 方法實作極其類似,不過在這裡集合使用的是

server

對象的

sadd()

操作,也就是集合不再是簡單的一個簡單資料結構了,在這裡直接換成了資料庫的存儲方式。

request.py

從上圖

request_seen()

方法中注意到

request_fingerprint()

方法,

request_fingerprint()

是擷取指紋,這裡Scrapy-Redis是直接用的Scrapy的方法。檔案路徑

scrapy.utils.request.py

Scrapy-Redis手動添加添加去重url(指紋)

從源碼可以看到指紋是通過

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')

           

如果覺得文章對你有幫助,能否幫我留一個贊。

繼續閱讀