在子函数中发起Scrapy请求报错:返回generator的快速解决咨询
解决Scrapy子函数请求返回Generator报错的问题
我之前刚碰到过完全一样的坑!你报错的原因很明确:Scrapy的parse方法(或者任何回调方法)要求返回的是Request、BaseItem、字典或者None,但你现在在parse里直接yield self.subfunc(link),其实是把整个生成器对象给yield出去了,而不是生成器里的Request对象,这就触发了那个错误。
快速解决方法(两种可选)
方法1:用for循环展开生成器
在parse里遍历子函数返回的生成器,逐个yield里面的Request:
import scrapy import csv class MySpider(scrapy.Spider): name = "my_spider" start_urls = ["https://example.com"] def parse(self, response): # 假设link是你要处理的目标链接 link = response.css("a::attr(href)").get() # 遍历子函数的生成器,逐个yield Request对象 for request in self.subfunc(link): yield request def subfunc(self, link): # 子函数返回包含Request的生成器 yield scrapy.Request(link, callback=self.handle_response) def handle_response(self, response): # 提取你需要的数据 item_data = { "title": response.css("h1::text").get(default=""), "url": response.url } # 直接写入CSV,无需yield任何内容 with open("result.csv", "a", encoding="utf-8", newline="") as f: writer = csv.DictWriter(f, fieldnames=["title", "url"]) # 第一次写入时添加表头 if f.tell() == 0: writer.writeheader() writer.writerow(item_data)
方法2:用yield from简化代码(Python3.3+支持)
yield from是Python专门用来展开生成器的语法,比for循环更简洁直观:
def parse(self, response): link = response.css("a::attr(href)").get() # 直接用yield from展开子函数的生成器,传递里面的Request yield from self.subfunc(link) def subfunc(self, link): yield scrapy.Request(link, callback=self.handle_response)
为什么这样能解决问题?
subfunc返回的是一个生成器对象,而yield from(或者for循环遍历)会把这个生成器里的每一个元素(也就是你yield的scrapy.Request)逐个传递出去,这样Scrapy就能拿到它期望的Request对象,而不是一个生成器本身。
关于自行写入CSV的注意点
你提到不需要yield条目或字典,那就在回调函数(比如上面的handle_response)里直接处理文件写入就行。注意要处理好文件打开的细节:用a模式追加写入,加上newline=""避免CSV出现空行,同时记得指定编码(比如encoding="utf-8")防止乱码。
内容的提问来源于stack exchange,提问作者emanuel cristian Mocean
相关产品推荐
相关产品推荐

