Scrapy去重失效求助:self.ids_seen集合始终为空
解决Scrapy去重Pipeline中
self.ids_seen始终为空的问题 嗨,刚瞅了你的代码片段,发现俩关键问题导致去重失效、self.ids_seen一直是空集合,咱们一步步来 fix:
1. 别忘启用Pipeline!
Scrapy不会自动加载你写的Pipeline类,必须在项目的settings.py里配置ITEM_PIPELINES,把你的DuplicatesPipeline加进去:
ITEM_PIPELINES = { # 如果你还有其他Pipeline(比如数据库存储的),也可以放在这里 '你的项目名.pipelines.DuplicatesPipeline': 300, # 优先级数值按需调整,300是中等偏前的位置 }
优先级数值越小,Pipeline执行越早,去重逻辑一般放在前面比较合理,能避免后续Pipeline做无用功。
2. 核心bug:没把处理过的id加入集合!
看你贴的process_item代码,只判断了item['id']是否在self.ids_seen里,但完全没把新的id添加到集合中!这样集合永远是空的,根本没法记录已爬的id。修改后的代码应该是这样:
from scrapy.exceptions import DropItem # 别忘了导入DropItem异常! import logging class DuplicatesPipeline(object): def __init__(self): self.ids_seen = set() logging.warning(self.ids_seen) # 这里初始化时空集合是正常的,别慌 def process_item(self, item, spider): if item['id'] in self.ids_seen: raise DropItem(f"Duplicate item found with id: {item['id']}") else: self.ids_seen.add(item['id']) # 关键!把当前item的id加入集合 return item # 必须返回item,让后续Pipeline继续处理它
另外你之前的代码里没写return item,如果漏掉这个,后面的数据库Pipeline就拿不到这个item了,这也是个容易踩的坑。
小提醒:内存去重的局限性
self.ids_seen是存在于Pipeline实例的内存里的,每次重启爬虫都会被清空。如果需要跨爬虫运行的持久化去重,你得把已爬id存在Redis、数据库或者本地文件里,但新手阶段先搞定当前的内存去重就好啦。
先试试上面这两个修改,应该就能解决你的问题了!
内容的提问来源于stack exchange,提问作者Octorber12
相关产品推荐
相关产品推荐

