Scrapy中属性分配至错误Item问题求助
问题根源:实例变量的共享冲突
你遇到的核心问题是**self.property作为Spider类的实例变量,会被所有并发的请求共享**。Scrapy是异步运行的,当你同时处理多个ProjectItem的爬取请求时,不同parse2回调会同时往同一个self.property列表里添加数据,导致属性被多个Item交叉覆盖,最终出现分配错误的情况。
举个具体场景:你刚启动第一个Item的parse2并开始收集属性,还没爬完所有分页,第二个Item的parse2就开始往同一个self.property里加内容,等第一个Item爬完最后一页时,self.property里已经混进了第二个Item的数据,自然就错配了。
修复方案:用请求的
meta存储单个Item的临时属性 把每个Item对应的属性列表存在该请求链的meta中,而不是用类实例变量。这样每个Item的爬取流程都有独立的临时存储,不会互相干扰。修改后的代码如下:
... def parse(self, response): for one_item in response.xpath('path1'): item = ProjectItem() # 为当前Item初始化独立的属性列表,存入请求meta request = scrapy.Request(one_item.xpath('path2').get(), callback=self.parse2) request.meta['item'] = item request.meta['property'] = [] yield request def parse2(self, response): item = response.meta['item'] # 取出当前Item专属的属性列表,而非共享的self.property property_list = response.meta['property'] for x in response.xpath('path3'): # 往专属列表添加实际内容(原代码漏了xpath结果提取) property_list.append(x.xpath('path4').get()) next_page = response.xpath('path5').get() if next_page is not None: request2 = scrapy.Request(next_page, callback=self.parse2) request2.meta['item'] = item # 传递当前属性列表到下一页请求 request2.meta['property'] = property_list yield request2 else: item['field'] = property_list yield item
关键修改点说明
- 移除了全局的
self.property类变量,改为在parse阶段为每个Item创建独立的属性列表,存入请求meta - 在
parse2中从当前请求的meta取出专属列表,避免多请求间的数据干扰 - 翻页时将当前属性列表传递给下一页请求,保证整个分页流程使用同一个列表
- 补全了原代码中缺失的xpath结果提取方法(
get()),避免存入无效的xpath对象
额外提醒
Scrapy的请求是异步并发执行的,永远不要用Spider的实例变量存储单个请求/Item的临时数据,所有和单个Item绑定的临时状态,都应该通过meta在请求链中传递,这样才能保证每个Item的数据独立性。
内容的提问来源于stack exchange,提问作者gongarek
相关产品推荐
相关产品推荐

