如何在scrapy中基于url过滤重复请求

nik*_*k-v 40 python web-crawler scrapy

我正在为使用CrawlSpider scrapy的网站编写一个爬虫.

Scrapy提供了一个内置的重复请求过滤器,可根据URL过滤重复的请求.此外,我可以使用CrawlSpider的规则成员过滤请求.

我想要做的是过滤以下请求:

http:://www.abc.com/p/xyz.html?id=1234&refer=5678
Run Code Online (Sandbox Code Playgroud)

如果我已经访问过

http:://www.abc.com/p/xyz.html?id=1234&refer=4567
Run Code Online (Sandbox Code Playgroud)

注意: refer是一个不影响我得到的响应的参数,所以我不在乎该参数的值是否发生变化.

现在,如果我有一个累积所有ID的集合,我可以在我的回调函数parse_item(这是我的回调函数)中忽略它来实现此功能.

但这意味着当我不需要时,我至少仍然会抓住那个页面.

那么我告诉scrapy它不应该基于url发送特定请求的方式是什么?

小智 40

您可以编写自定义中间件以进行重复删除,并将其添加到设置中

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)
Run Code Online (Sandbox Code Playgroud)

然后,您需要在settings.py中设置正确的DUPFILTER_CLASS

DUPEFILTER_CLASS = 'scraper.duplicate_filter.CustomFilter'
Run Code Online (Sandbox Code Playgroud)

它应该在那之后工作


Abe*_*ker 10

在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)
Run Code Online (Sandbox Code Playgroud)

正如ytomar所提到的,一定要将DUPEFILTER_CLASS常量添加到settings.py:

DUPEFILTER_CLASS = 'scraper.custom_filters.SeenURLFilter'
Run Code Online (Sandbox Code Playgroud)