我写一个履带使用scrapy与CrawlSpider网站。
Scrapy提供了过滤是基于URL的重复请求一个内置的重复请求过滤器。 另外,我可以使用CrawlSpider 规则成员过滤请求。
我想要做的是像过滤要求:
http:://www.abc.com/p/xyz.html?id=1234&refer=5678
如果我已经访问过
http:://www.abc.com/p/xyz.html?id=1234&refer=4567
注:指的是不影响我得到的响应参数,所以我不在乎如果该参数的值更改。
现在,如果我有一组聚集所有的ID,我可以忽视它在我的回调函数parse_item(这是我的回调函数)来实现这一功能。
但是,这将意味着我仍然至少获取该网页,当我不需要。
那么,什么是我可以告诉scrapy,它不应该发送基于URL中的特定请求的方式吗?
你可以写重复的去除定制的中间件和在设置中添加它
import os
from scrapy.dupefilter import RFPDupeFilter
class CustomFilter(RFPDupeFilter):
"""A dupe filter that considers specific ids in the url"""
def __getid(self, url):
mm = url.split("&refer")[0] #or something like that
return mm
def request_seen(self, request):
fp = self.__getid(request.url)
if fp in self.fingerprints:
return True
self.fingerprints.add(fp)
if self.file:
self.file.write(fp + os.linesep)
然后,你需要设置在settings.py正确DUPFILTER_CLASS
DUPEFILTER_CLASS = 'scraper.duplicate_filter.CustomFilter'
它应该在这之后的工作
继ytomar的带领下,我写了这个过滤器,滤波器完全基于已经被看到通过检查内存中的URL集合。 我是一个Python菜鸟,所以让我知道,如果我搞砸了的东西,但它似乎工作好吗:
from scrapy.dupefilter import RFPDupeFilter
class SeenURLFilter(RFPDupeFilter):
"""A dupe filter that considers the URL"""
def __init__(self, path=None):
self.urls_seen = set()
RFPDupeFilter.__init__(self, path)
def request_seen(self, request):
if request.url in self.urls_seen:
return True
else:
self.urls_seen.add(request.url)
作为ytomar提到,一定要添加DUPEFILTER_CLASS
常数settings.py
:
DUPEFILTER_CLASS = 'scraper.custom_filters.SeenURLFilter'
https://github.com/scrapinghub/scrapylib/blob/master/scrapylib/deltafetch.py
该文件可能会帮助您。 此文件创建唯一的增量的一个数据库中获取从URL键,用户通过在一个scrapy.Reqeust(甲基= {“deltafetch_key”:uniqe_url_key})。 这本让你避免你已经在过去的访问重复的请求。
使用deltafetch.py样本实施的mongodb
if isinstance(r, Request):
key = self._get_key(r)
key = key+spider.name
if self.db['your_collection_to_store_deltafetch_key'].find_one({"_id":key}):
spider.log("Ignoring already visited: %s" % r, level=log.INFO)
continue
elif isinstance(r, BaseItem):
key = self._get_key(response.request)
key = key+spider.name
try:
self.db['your_collection_to_store_deltafetch_key'].insert({"_id":key,"time":datetime.now()})
except:
spider.log("Ignoring already visited: %s" % key, level=log.ERROR)
yield r
例如。 ID = 345 scrapy.Request(URL,元= {deltafetch_key:345},回调=解析)
这里是scrapy 0.24.6我的自定义过滤器基地。
在此过滤器,它只在乎ID在URL中。 例如
http://www.example.com/products/cat1/1000.html?p=1
http://www.example.com/products/cat2/1000.html?p=2
被视为同一个URL。 但
http://www.example.com/products/cat2/all.html
将不会。
import re
import os
from scrapy.dupefilter import RFPDupeFilter
class MyCustomURLFilter(RFPDupeFilter):
def _get_id(self, url):
m = re.search(r'(\d+)\.html', url)
return None if m is None else m.group(1)
def request_fingerprint(self, request):
style_id = self._get_id(request.url)
return style_id