Scrapy中request正常但request2报KeyError: 'pitem'问题求助
嘿,我来帮你搞定这个Scrapy Request的问题!
问题根源分析
你遇到的KeyError: 'pitem'本质是Request的meta参数传递不完整/有误,而且你可能对Scrapy Request的meta机制有点误解:每个scrapy.Request的meta是独立的字典,不会自动继承上一个Request的meta内容,必须显式把需要的参数传进去。
看你的代码细节:
- 从
parse发的第一个Request,meta里只传了item,但parse2一上来就取response.meta['pitem']——按道理这一步就会报错,但你说第一个请求正常,可能你实际代码里parse中给meta加了pitem但贴代码时漏了? - 重点是你在
parse2里发request2时,只给meta传了pitem = item,如果下一次进入parse2时还需要依赖其他参数,就会因为meta里没有对应键报错;如果是pitem找不到,那大概率是你发送request2时的参数赋值写错了(比如拼写错误、变量名搞混)。
具体修复方案
1. 确保每次Request的meta包含所有回调需要的参数
如果parse2需要同时用到item和pitem,那每次发Request时都要把这两个参数放进meta:
# 在parse方法里发送第一个Request时 def parse(self, response): ... # 假设你已经创建了item和pitem对象 request = scrapy.Request(link, callback=self.parse2) request.meta['item'] = item request.meta['pitem'] = pitem # 必须加上这行,parse2才能取到pitem yield request
# 在parse2里发送request2时 def parse2(self, response): item = response.meta['item'] pitem = response.meta['pitem'] ... pitem['field'].append(self.whatever) if next_page is not None: request2 = scrapy.Request(next_page, callback=self.parse2) # 把需要的参数都传入meta,避免遗漏 request2.meta['item'] = item request2.meta['pitem'] = pitem yield request2 else: yield pitem self.whatever = []
2. 更高效的meta继承方式
如果需要传递的参数很多,不想手动一个个写,可以用response.meta.copy()复制上一个Request的meta,再修改需要更新的参数:
def parse2(self, response): item = response.meta['item'] pitem = response.meta['pitem'] ... if next_page is not None: request2 = scrapy.Request(next_page, callback=self.parse2) # 复制之前的meta,自动继承所有参数 request2.meta = response.meta.copy() # 如果需要更新某个参数,再单独赋值 request2.meta['pitem'] = updated_pitem # 比如你要更新pitem的话 yield request2
3. 修复实例变量共享的隐患
另外注意self.whatever是爬虫的实例变量,多个并发的Request回调会共享这个变量,很容易导致数据混乱。建议把它也放进meta里,作为每个Request的独立变量:
def parse(self, response): ... request = scrapy.Request(link, callback=self.parse2) request.meta['item'] = item request.meta['pitem'] = pitem request.meta['whatever'] = [] # 每个Request初始化自己的whatever yield request def parse2(self, response): item = response.meta['item'] pitem = response.meta['pitem'] whatever = response.meta['whatever'] # 从meta取当前Request的whatever ... pitem['field'].append(whatever) if next_page is not None: request2 = scrapy.Request(next_page, callback=self.parse2) request2.meta = response.meta.copy() request2.meta['whatever'] = [] # 重置新Request的whatever yield request2 else: yield pitem
最后排查小技巧
如果还是出现KeyError: 'pitem',检查这两点:
- 发送
request2时,是不是真的给request2.meta['pitem']赋值了?有没有拼写错误(比如写成'item')? - 赋值的变量是不是正确的?比如是不是应该传
pitem而不是item?
内容的提问来源于stack exchange,提问作者gongarek
相关产品推荐
相关产品推荐

