请求去重
这是爬虫岗一道高频出现的面试题:
Q:对于重复的请求,scrapy是如何去重的?去重原理是什么?请求是如何计算唯一性的?
带着这个问题,进入今天的主题。
DUPEFILTER_CLASS
在scrapy项目配置中,DUPEFILTER_CLASS
是框架对请求去重规则的设置项。默认的类路径:scrapy.dupefilters.RFPDupeFilter
。
进入到文件中,观察到类RFPDupeFilter继承自BaseDupeFilter,而BaseDupeFilter似乎什么都没做,只是定义了一些方法。所以,真正的去重核心代码都在RFPDupeFilter类中。逐行分析下其原理。
RFPDupeFilter
class RFPDupeFilter(BaseDupeFilter):
"""Request Fingerprint duplicates filter"""
def __init__(self, path=None, debug=False):
self.file = None
# 用python内置set()作为请求的指纹
# set的特性:无序不重复元素集
self.fingerprints = set()
self.logdupes = True
self.debug = debug
self.logger = logging.getLogger(__name__)
# 本地持久化请求指纹
if path:
self.file = open(os.path.join(path, 'requests.seen'), 'a+')
self.file.seek(0)
self.fingerprints.update(x.rstrip() for x in self.file)
@classmethod
def from_settings(cls, settings):
# 配置中开启DEBUG,就会持久化文件
debug = settings.getbool('DUPEFILTER_DEBUG')
return cls