Scrapy二次任务表单请求报错:返回类型应为Request等而非list
解决Scrapy回调返回List的报错问题
这个报错我太熟悉了!本质是Scrapy对爬虫回调函数的返回值类型有严格限制——它只接受Request、BaseItem、dict或者None类型的单个对象,或者能产出这些对象的生成器/可迭代对象。你应该是在处理POST表单请求的回调里,直接用return返回了一个列表,导致Scrapy把整个列表当成了一个不符合要求的返回对象,所以触发了这个错误。
具体解决方法
1. 改用yield逐个产出结果
把原来的return [对象1, 对象2]拆成多个yield语句,逐个返回每个合法的对象。这是Scrapy最推荐的写法,因为它支持异步处理,内存占用也更低。
2. 用yield from迭代列表(简洁写法)
如果你的逻辑里已经生成了一个包含合法对象的列表,可以用yield from来一次性迭代产出所有元素,效果和逐个yield完全一样,代码更紧凑。
3. 检查所有回调函数的返回语句
仔细排查你处理POST响应的回调函数,确保没有任何return语句直接返回列表。哪怕是返回空结果,也应该用return None或者直接不写return(默认返回None),而不是return []。
错误与正确代码示例
错误写法(触发报错)
def parse_post_response(self, response): result_items = [] # 解析页面数据 for item_selector in response.css('.result-row'): item = MyCustomItem() item['title'] = item_selector.css('.title::text').get() item['url'] = item_selector.css('a::attr(href)').get() result_items.append(item) # 直接返回列表,违反Scrapy规则 return result_items
正确写法1(逐个yield)
def parse_post_response(self, response): # 解析页面数据 for item_selector in response.css('.result-row'): item = MyCustomItem() item['title'] = item_selector.css('.title::text').get() item['url'] = item_selector.css('a::attr(href)').get() # 逐个产出Item对象 yield item # 如果需要继续发起请求,同样用yield yield scrapy.Request(url='http://example.com/next-page', callback=self.parse_next)
正确写法2(yield from迭代列表)
def parse_post_response(self, response): result_items = [] # 解析页面数据 for item_selector in response.css('.result-row'): item = MyCustomItem() item['title'] = item_selector.css('.title::text').get() item['url'] = item_selector.css('a::attr(href)').get() result_items.append(item) # 用yield from迭代产出所有Item yield from result_items # 同样可以混合yield Request yield scrapy.Request(url='http://example.com/next-page', callback=self.parse_next)
只要把返回列表的逻辑改成上述两种方式,这个报错就会消失,Scrapy也能正常处理你的爬取结果和后续请求了。
内容的提问来源于stack exchange,提问作者Fredo De Bretagne
相关产品推荐
相关产品推荐

