如何向Scrapy传递非正则表达式的‘禁止爬取’URL列表?
解决Scrapy传入禁止爬取URL列表的问题
方法一:将URL列表转为正则表达式列表
LinkExtractor的deny参数支持正则表达式字符串列表,你可以把每个目标URL转成匹配完整路径的正则规则,避免部分匹配或特殊字符冲突:
- 用
re.escape()处理URL中的特殊符号(如?、&),防止正则语法报错 - 给每个处理后的URL加上
^和$,确保只匹配完整的目标URL
示例代码:
import re from scrapy.linkextractors import LinkExtractor # 已索引的URL列表 indexed_urls = [ "https://example.com/job/123", "https://example.com/job/456?source=sitemap" ] # 转换为符合要求的正则列表 deny_patterns = [f"^{re.escape(url)}$" for url in indexed_urls] # 在LinkExtractor中使用 link_extractor = LinkExtractor(deny=deny_patterns)
方法二:利用Scrapy内置去重机制(更适配你的场景)
既然你的需求是每日爬取新页面、跳过已索引内容,直接用Scrapy的去重过滤器更高效,不需要手动处理deny参数:
- 将已索引URL加载到Scrapy的去重队列,框架会自动跳过重复请求
- 可在爬虫初始化时批量导入历史URL到去重器中
示例代码(基于SitemapSpider):
import scrapy from scrapy.spiders import SitemapSpider class JobCrawler(SitemapSpider): name = 'job_crawler' sitemap_urls = ['https://example.com/sitemap.xml'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 从文件加载已索引URL(假设每行一个URL) with open('indexed_urls.txt', 'r') as f: indexed_urls = set(f.read().splitlines()) # 获取去重过滤器实例,批量添加已爬URL的指纹 dupe_filter = self.crawler.engine.downloader.middlewares['scrapy.downloadermiddlewares.duplicates.DupeFilter'] for url in indexed_urls: request_fingerprint = self.crawler.request_fingerprint(scrapy.Request(url)) dupe_filter.seen.add(request_fingerprint)
两种方法对比
- 方法一适合少量URL的精确过滤,但URL数量过大时,正则列表会影响提取性能
- 方法二更符合Scrapy的设计逻辑,适配大规模去重场景,推荐用于你的每日爬取需求
内容的提问来源于stack exchange,提问作者Nash Reilly
相关产品推荐
相关产品推荐

