Scrapy爬需跳转两次URL,导出CSV数据乱序重复问题求助
Scrapy多级爬取数据乱序、重复问题解决方案
问题描述
我尝试从一个需要先访问2个URL才能爬取数据的网站获取数据,目标是得到指定格式的导出文件。我的代码如下:
import scrapy from scrapy.item import Item, Field from scrapy import Request class myItems(Item): info1 = Field() info2 = Field() info3 = Field() info4 = Field() class mySpider(scrapy.Spider): name = 'techbot' start_urls = [''] def parse(self, response): #Extracts first link items = [] list1 = response.css("").extract() #extract all info from here for i in list1: link1 = 'https:...' + str(i) request = Request(link1, self.parseInfo1, dont_filter =True) request.meta['item'] = items yield request yield items def parseInfo1(self, response): #Extracts second link item = myItems() items = response.meta['item'] list1 = response.css("").extract() for i in list1: link1 = '' + str(i) request = Request(link1, self.parseInfo2, dont_filter =True) request.meta['item'] = items items.append(item) return request def parseInfo2(self, response): #Extracts all data item = myItems() items = response.meta['item'] item['info1'] = response.css("").extract() item['info2'] = response.css("").extract() item['info3'] = response.css("").extract() item['info4'] = response.css("").extract() items.append(item) return items
我在终端执行命令
scrapy crawl techbot运行爬虫后,得到的数据出现乱序和重复问题,例如第一组数据被多次爬取,其余数据顺序混乱。恳请各位指点如何获取符合初始要求的规整格式数据,谢谢。
问题根源分析
我看了你的代码,核心问题出在Item的传递和数据收集逻辑混乱上:
- 你在
parse里创建了一个全局的items列表,所有请求都共享这个列表,导致多个请求同时往里面加数据,自然会出现重复和乱序。 parseInfo1和parseInfo2里重复创建myItems()实例,还错误地把整个列表绑定到request的meta中,而不是单个Item,最终导致数据被多次添加。parse方法最后直接yield items,但此时异步请求还没完成,会提前输出空列表,后续parseInfo2又往同一个列表里塞数据,进一步加剧混乱。
修正后的代码
下面是调整后的代码,解决了上述问题,保证数据规整:
import scrapy from scrapy.item import Item, Field from scrapy import Request class myItems(Item): info1 = Field() info2 = Field() info3 = Field() info4 = Field() class mySpider(scrapy.Spider): name = 'techbot' # 替换成你的实际起始URL start_urls = ['https://your-start-url.com'] def parse(self, response): # 提取第一级链接,替换成你的实际CSS选择器 first_level_links = response.css("your-first-link-selector::attr(href)").extract() for link_suffix in first_level_links: full_link = 'https://your-base-domain.com' + link_suffix # 调度第一级页面请求,不需要提前创建Item yield Request(full_link, callback=self.parseInfo1, dont_filter=True) def parseInfo1(self, response): # 提取第二级链接,替换成你的实际CSS选择器 second_level_links = response.css("your-second-link-selector::attr(href)").extract() for link_suffix in second_level_links: full_link = 'https://your-base-domain.com' + link_suffix # 为每个第二级请求创建独立的Item,绑定到meta中 item = myItems() # 如果第一级页面有需要保存的字段,在这里赋值 # item['some_field_from_level1'] = response.css(...) yield Request(full_link, callback=self.parseInfo2, meta={'item': item}, dont_filter=True) def parseInfo2(self, response): # 获取当前请求绑定的独立Item item = response.meta['item'] # 提取目标数据,用extract_first()获取单个值,strip()清理格式 item['info1'] = response.css("info1-selector::text").extract_first(default='').strip() item['info2'] = response.css("info2-selector::text").extract_first(default='').strip() item['info3'] = response.css("info3-selector::text").extract_first(default='').strip() item['info4'] = response.css("info4-selector::text").extract_first(default='').strip() # 直接输出单个Item,Scrapy会自动处理数据收集和导出 yield item
关键修正说明
- 独立Item绑定:每个第二级请求都对应一个独立的
myItems实例,避免多个请求共享同一个Item导致数据覆盖或重复。 - 异步请求正确调度:所有请求都通过
yield交给Scrapy调度,框架会按请求顺序处理,保证数据的顺序性(只要网站结构允许)。 - 移除全局列表:不再用全局列表收集数据,而是在最终解析方法里直接
yield单个Item,让Scrapy自动处理数据的存储和导出,避免异步请求未完成就提前输出。 - 优化数据提取:用
extract_first()替代extract()获取单个字段值,加上default=''避免空值报错,strip()清理多余的空格和换行,让数据更规整。
内容的提问来源于stack exchange,提问作者thetin
相关产品推荐
相关产品推荐

