Scrapy Redis实现分布式爬取与缓存管理
import redis
from scrapy.dupefilters import RFPDupeFilter
from scrapy.utils.request import request_fingerprint
class RedisDupeFilter(RFPDupeFilter):
"""Redis 中的 URL 去重复过滤器"""
def __init__(self, server, key, debug=False):
self.server = server
self.key = key
self.debug = debug
self.rfp_count = 0
self._duplicates = set()
@classmethod
def from_settings(cls, settings):
server = redis.Redis(host=settings['REDIS_HOST'],
port=settings['REDIS_PORT'],
db=settings['REDIS_DB'])
key = 'dupefilter:%s' % settings.get('JOB_NAME', 'default')
return cls(server, key, settings.getbool('DUPEFILTER_DEBUG'))
def request_seen(self, request):
fp = request_fingerprint(request)
if self.server.sismember(self.key, fp):
self.rfp_count += 1
if self.debug:
print(" Fingerprint %s already seen; skipping" % fp)
return True
self.server.sadd(self.key, fp)
def close(self, reason):
self.server.srem(self.key, *list(self._duplicates))
self.server.save()
def log(self, request, spider):
msg = "Filtered duplicate request: %(request)s"
self.logger.debug(msg, {'request': request}, extra={'spider': spider})
这段代码定义了一个名为RedisDupeFilter
的类,它继承自Scrapy的RFPDupeFilter
。它使用Redis作为去重复存储的后端,而不是使用Scrapy默认的内存去重复过滤系统。这个类提供了from_settings
类方法来初始化Redis连接和去重复的key。request_seen
方法检查一个给定的请求的指纹是否已经在Redis的集合中。如果已经存在,则认为这个请求已经被处理过,返回True
表示请求被过滤掉了。close
方法在去重复过滤器不再需要时调用,用来清理Redis中的数据。log
方法用于记录被过滤掉的请求。
评论已关闭