You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用CrawlSpider和Rules对特定域名关闭去重过滤?

针对特定域名禁用Scrapy去重过滤的解决方案

你遇到的问题是特定域名的分页请求重定向回初始URL后被Scrapy的去重机制过滤,导致无法爬取。完全可以针对单个域名禁用去重,以下是几种可行的实现方式:

方法1:自定义域名专属去重中间件

继承Scrapy默认的去重中间件,对目标域名跳过去重检查:

from scrapy.downloadermiddlewares.duplicates import DuplicatesFilter
from scrapy.utils.request import request_fingerprint

class DomainSpecificDuplicatesFilter(DuplicatesFilter):
    def request_seen(self, request):
        # 替换成你需要禁用去重的目标域名
        target_domain = 'piwi.wiesbaden.de'
        if target_domain in request.url:
            return False  # 返回False表示未见过该请求,不触发去重
        # 其他域名沿用默认去重逻辑
        fp = request_fingerprint(request)
        if fp in self.fingerprints:
            return True
        self.fingerprints.add(fp)
        if self.file:
            self.file.write(fp + '\n')

在项目的settings.py中替换默认去重中间件:

DOWNLOADER_MIDDLEWARES = {
    '你的项目名.middlewares.DomainSpecificDuplicatesFilter': 300,
    'scrapy.downloadermiddlewares.duplicates.DuplicatesFilter': None,
}

方法2:在链接提取阶段添加去重豁免标记

修改LinkExtractor的process_links方法,给目标域名的链接对应的请求添加dont_filter=True参数:

from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

def process_links(links):
    target_domain = 'piwi.wiesbaden.de'
    for link in links:
        if target_domain in link.url:
            link.meta['dont_filter'] = True
    return links

class MySpider(CrawlSpider):
    name = 'spdr'
    start_urls = [
        i.strip() for i in open('list.txt', 'r').read().splitlines() if i and i.strip()
    ]
    rules = [
        Rule(
            LinkExtractor(
                allow=[], 
                restrict_css=[
                    "a[rel='next']",
                    "a[href*='nav_top-next']",
                ],
                process_links=process_links  # 启用自定义链接处理函数
            ),
            follow=True,
        ),
        # 其他规则...
    ]

方法3:用请求拦截中间件豁免目标域名

编写一个简单的下载中间件,拦截目标域名的请求并设置dont_filter=True:

class DomainDontFilterMiddleware:
    def process_request(self, request, spider):
        target_domain = 'piwi.wiesbaden.de'
        if target_domain in request.url:
            request.dont_filter = True
        return None

在settings.py中启用该中间件:

DOWNLOADER_MIDDLEWARES = {
    '你的项目名.middlewares.DomainDontFilterMiddleware': 543,
}

各方法适用场景

  • 方法1:适合多个爬虫需要统一处理同一域名的情况,全局生效无需修改爬虫代码。
  • 方法2:仅对当前Rule提取的分页链接生效,精准度高,不影响其他请求。
  • 方法3:实现最简单,所有目标域名的请求都会跳过去重,适合该域名下所有请求都不需要去重的场景。

内容的提问来源于stack exchange,提问作者Artsiom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 01:20:46