Scrapy 过滤器
当我们在爬取网页的时候可能会遇到一个调转连接会在不同页面出现,这个时候如果我们的爬虫程序不能识别出
该链接是已经爬取过的话,就会造成一种重复不必要的爬取。所以我们要对我们即将要爬取的网页进行过滤,把重
复的网页链接过滤掉
指纹过滤器
去重处理可以避免将重复性的数据保存到数据库中以造成大量的冗余性数据。不要在获得爬虫的结果后进行内容过
滤,这样做只不过是避免后端数据库出现重复数据
去重处理对于一次性爬取是有效的,但对于增量式爬网则恰恰相反。对于持续性长的增量式爬虫,应该进行"前置过
滤",这样可以有效地减少爬虫出动的次数。在发出请求之前检查询爬虫是否曾爬取过该URL,如果已爬取过,则让爬虫直接跳过该请求以避免重复出动爬虫
Scrapy 提供了一个很好的请求指纹过滤器(Request Fingerprint duplicates filter)
scrapy.dupefilters.ReppupeFilter ,当它被启用后,会自动记录所有成功返回响应的请求的URL,并将其以文件
(requests.seen)
方式保存在项目目录中。请求指纹过滤器的原理是为每个URL生成一个指纹并记录下来,一旦
当前请求的URL在指纹库中有记录,就自动跳过该请求。
默认情况下这个过滤器是自动启用的,但是在start_requests
中是关闭的,当然也可以根据自身的需求编写自定义的过滤器
起始 url ,默认过滤器关闭的地方
def start_requests(self):
for url in self.start_urls:
# 每一个url封装成Request对象,交给调度器
# 这里的dont_filter=True 默认关闭scrapy自带的过滤器,
yield Request(url, dont_filter=True) # 改为 False 为过滤
自定义过滤器
可以用 Scrapy 提供的 request_fingerprint
函数为请求生成指纹,然后将指纹写入内存,这样会从内存中存取数据会很快。
然后写好的这个类,位置可以随便放,但是一定要在 settings.py 文件中从新指定过滤器
放在中间件里
# 过滤器先启动,再执行爬虫
import hashlib
from scrapy.dupefilters import BaseDupeFilter
class URLFilter(BaseDupeFilter):
"""根据URL过滤"""
@classmethod
def from_settings(cls, settings):
# 从settings里面取到配置文件
debug = settings.getbool('DUPEFILTER_DEBUG')
return cls()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# 过滤url的集合
self.url_set = set()
def request_seen(self, request):
"""对每一个请求进行过滤"""
url = self.request_fingerprint(request)
if url in self.url_set:
# 返回True就代表这个url已经被请求过了
return True
else:
self.url_set.add(request.url)
def request_fingerprint(self, request):
# 返回由url摘要后的字符串
return hashlib.md5(request.url.encode()).hexdigest()
settings.py
DUPEFILTER_CLASS = 'mzt.middlewares.URLFilter'