如何在 Scrapy 中使用自定义的 Spider 去重策略进行 URL 去重和处理?

2023-04-17 00:00:00 自定义 策略 如何在

要实现自定义的 Spider 去重策略,需要继承 Scrapy 的 dupefilters.BaseDupeFilter 类,并实现 request_seen(request)open() 方法。其中 request_seen(request) 方法用于判断请求是否已经处理过,open() 方法用于打开去重数据存储。

首先需要创建一个新的去重策略类,在类中实现 request_seen(request)open() 方法。下面是一个简单的例子:

from scrapy.dupefilters import BaseDupeFilter
from scrapy.utils.request import request_fingerprint

class MyDupeFilter(BaseDupeFilter):
    def __init__(self, path=None):
        self.urls_seen = set()
        BaseDupeFilter.__init__(self, path)

    def request_seen(self, request):
        url = request.url.split('?')[0]
        finger = request_fingerprint(request)
        if url in self.urls_seen:
            return True
        self.urls_seen.add(url)
        self.file.write(finger + '\n')
        return False

    def open(self):
        self.file = open(self.file_path, 'a+')
        self.urls_seen = set(line.strip() for line in self.file)

在该例子中,request_seen(request) 方法使用了一个 set 类型的变量 urls_seen 来存储已经处理过的请求的 url,通过检查 url 是否已经存在来判断当前请求是否已经被处理过。如果当前请求没有被处理过,则将其 fingerprint(可以理解为请求的唯一标识)写入文件,并且返回 False 表示该请求需要被处理。open() 方法会打开一个文件并读取其中已经存在的 fingerprint,存储在 urls_seen 变量中,以便后续查询。

下一步是将自定义的去重策略类与 Spider 建立关联。要实现这一点,需要在 Spider 中添加一个 DUPEFILTER_CLASS 属性,该属性值为自定义的去重策略类。例如,以下是使用自定义去重策略类的演示:

import scrapy

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        "http://pidancode.com/",
        "http://pidancode.com/2018-01-01",
        "http://pidancode.com/2018-01-02",
        "http://pidancode.com/2018-01-03",
        "http://pidancode.com/2018-01-04",
        "http://pidancode.com/2018-01-05",
        "http://pidancode.com/2018-01-06",
        "http://pidancode.com/2018-01-07"
    ]
    custom_settings = {
        'DUPEFILTER_CLASS': 'myproject.dupefilter.MyDupeFilter',
    }

    def parse(self, response):
        pass

这个例子中,我们定义了一个名为 MySpider 的 Spider,并指定了 DUPEFILTER_CLASS 属性为我们定义的去重策略类 myproject.dupefilter.MyDupeFilter。此后我们在该 Spider 中的请求就会使用自定义去重策略进行去重。

最后,需要注意的是,在使用自定义去重策略时,与默认的去重策略不一样的是,对于同一个 url 不同的查询参数,也会被认为是不同的,因此需要对 URL 进行处理,只保留前面的部分。例如,在上述去重类中,我们将 URL 的查询参数部分去掉了,只保留了 URL 的前半部分。

相关文章