如何从scrapy.follow获取字符串列表?Scrapy多页面爬取数据合并问题
解决Scrapy合并列表页与详情页数据的问题
你遇到的核心问题是:Scrapy的response.follow返回的是异步请求对象,不是直接的页面内容,所以没法直接把它放到输出的字典里。要合并列表页的标题和详情页的内容,需要利用Scrapy的回调传参机制,把标题传递给详情页的处理函数,拿到内容后再一起输出。
推荐方案:逐个输出单个活动的完整信息
这种方式符合Scrapy的异步流式处理逻辑,每个活动的标题和详情一一对应输出,高效且易维护:
class TextSpider(scrapy.Spider): name = "text" def parse(self, response): # 遍历列表页的标题与对应URL,一一配对处理 for title, url in zip( response.css('div.recomedBox_item_min_title p a::text').getall(), response.css('div.recomedBox_item_min_title p a::attr(href)').getall() ): # 通过meta参数把当前活动的标题传递给详情页回调函数 yield response.follow(url, self.extract_info, meta={"conference_title": title}) def extract_info(self, response): # 从meta中取出传递过来的标题 title = response.meta["conference_title"] # 提取详情页内容 content = ' '.join(response.css('div.txt_body.img p::text').getall()) # 输出包含标题与内容的完整条目 yield { "conference_title": title, "conference_content": content }
可选方案:输出包含所有标题和内容的大字典
如果需要把所有活动的标题和内容整理成一个大字典(两个列表分别对应),可以通过收集结果的方式实现(注意:这种方式需要等待所有详情页请求完成,不适合数据量很大的场景):
class TextSpider(scrapy.Spider): name = "text" def parse(self, response): # 先保存所有标题和URL self.conference_titles = response.css('div.recomedBox_item_min_title p a::text').getall() self.conference_urls = response.css('div.recomedBox_item_min_title p a::attr(href)').getall() self.conference_contents = [None] * len(self.conference_titles) # 发起所有详情页请求,传递索引用于对应内容位置 for idx, url in enumerate(self.conference_urls): yield response.follow(url, self.extract_info, meta={"item_idx": idx}) def extract_info(self, response): idx = response.meta["item_idx"] content = ' '.join(response.css('div.txt_body.img p::text').getall()) # 按索引把内容放到对应位置,确保和标题顺序一致 self.conference_contents[idx] = content # 当所有内容都收集完成后,输出大字典 if None not in self.conference_contents: yield { "conference_titles": self.conference_titles, "conference_content": self.conference_contents }
关键说明
meta是Scrapy中在请求之间传递数据的常用方式,能把列表页的上下文(比如标题、索引)传递给详情页的回调函数。- 推荐使用第一种方案,因为Scrapy的设计初衷就是流式处理数据,逐个输出条目更高效,也能避免因等待大量请求导致的内存占用问题。
内容的提问来源于stack exchange,提问作者Lei Hao
相关产品推荐
相关产品推荐

