Scrapy爬取谷歌专利数据时如何将重复化学品的专利号追加到MongoDB数组
解决方案
问题原因
你当前的Pipeline逻辑是每爬取一页搜索结果就直接向MongoDB插入一条新记录,所以同一化学品多页结果会生成多条chemical字段重复的记录,每页仅存储对应当页的公开号。
修改方案
仅需要调整pipelines.py中的process_item方法,使用MongoDB的upsert(存在则更新,不存在则插入)操作即可实现需求,同时还可自动对公开号去重:
修改后的pipelines.py代码
import pymongo from itemadapter import ItemAdapter class PattentsPipeline(object): collection_name = 'items' def __init__(self, mongo_uri, mongo_db): self.mongo_uri = mongo_uri self.mongo_db = mongo_db @classmethod def from_crawler(cls, crawler): return cls( mongo_uri=crawler.settings.get('MONGO_URI'), mongo_db=crawler.settings.get('MONGO_DATABASE', 'items') ) def open_spider(self, spider): self.client = pymongo.MongoClient(self.mongo_uri) self.db = self.client[self.mongo_db] # 可选优化:给chemical字段加唯一索引,避免并发场景下重复插入 self.db[self.collection_name].create_index('chemical', unique=True) def close_spider(self, spider): self.client.close() def process_item(self, item, spider): item_data = ItemAdapter(item).asdict() self.db[self.collection_name].update_one( # 查询条件:匹配相同化学品的记录 {'chemical': item_data['chemical']}, # 更新操作:往publication_number数组追加新公开号,自动去重 { '$addToSet': { 'publication_number': { '$each': item_data['publication_number'] } } }, # 没有匹配记录时自动插入新记录 upsert=True ) return item
操作说明
$addToSet:MongoDB内置操作符,往数组中添加元素时自动跳过已存在的元素,避免公开号重复$each:支持一次性传入数组批量添加多个元素,适配单页返回多个公开号的场景upsert=True:开启更新插入模式,完全匹配“存在则追加、不存在则新增”的需求
内容的提问来源于stack exchange,提问作者chris_
相关产品推荐
相关产品推荐

