Scrapy脚本中Pandas写入Excel无法追加,总是覆盖行的问题解决
问题原因分析
- Excel写入位置未指定:使用
mode='a'和if_sheet_exists='overlay'时,pandas默认从工作表第2行(表头行之后)开始写入新数据,每次parse方法执行都会覆盖该位置起始的行,而非追加到现有数据末尾。 - 全局变量异步冲突:
plate_num_xlsx作为全局变量,Scrapy异步处理多个请求时,后续请求会覆盖该变量值,导致plate_num_xlsx==plate.replace(" ","").strip()的匹配逻辑出错,数据对应关系混乱。 - 频繁IO操作隐患:每个请求的
parse阶段都打开并写入Excel文件,不仅效率低下,还可能因异步并发写入导致数据覆盖或损坏。
修复方案
核心修改点
- 用Scrapy的
meta参数传递车牌号码,替代全局变量,避免异步冲突。 - 统一收集所有爬取到的数据,在爬虫结束时一次性写入Excel,实现真正的追加功能。
修改后的完整代码
import scrapy from scrapy.crawler import CrawlerProcess import pandas as pd class plateScraper(scrapy.Spider): name = 'scrapePlate' allowed_domains = ['dvlaregistrations.direct.gov.uk'] # 类变量,用于统一收集所有爬取到的item all_items = [] def start_requests(self): df = pd.read_excel('data.xlsx') columnA_values = df['PLATE'] for plate_num in columnA_values: base_url = f"https://dvlaregistrations.direct.gov.uk/search/results.html?search={plate_num}&action=index&pricefrom=0&priceto=&prefixmatches=¤tmatches=&limitprefix=&limitcurrent=&limitauction=&searched=true&openoption=&language=en&prefix2=Search&super=&super_pricefrom=&super_priceto=" # 通过meta传递当前车牌号码,避免全局变量冲突 yield scrapy.Request(url=base_url, meta={'plate_num': plate_num}) def parse(self, response): plate_num = response.meta['plate_num'] for row in response.css('div.resultsstrip'): plate = row.css('a::text').get() price = row.css('p::text').get() if plate_num == plate.replace(" ", "").strip(): item = {"plate": plate.strip(), "price": price.strip()} else: item = {"plate": plate.strip(), "price": "-"} self.all_items.append(item) yield item def closed(self, reason): """爬虫结束时执行的方法,统一写入数据到Excel""" df_output = pd.DataFrame(self.all_items) try: # 读取现有Excel文件中的数据 existing_df = pd.read_excel('output_res.xlsx', sheet_name='result') # 合并现有数据与新爬取数据 combined_df = pd.concat([existing_df, df_output], ignore_index=True) except FileNotFoundError: # 如果文件不存在,直接使用新爬取的数据 combined_df = df_output # 写入Excel combined_df.to_excel('output_res.xlsx', sheet_name='result', index=False) process = CrawlerProcess() process.crawl(plateScraper) process.start()
关键细节说明
- meta参数传递:在
start_requests中,将当前循环的车牌号码通过meta字典传递给请求,在parse方法中从response.meta取出,确保每个请求处理的车牌号码唯一且不被覆盖。 - 统一收集数据:使用类变量
all_items存储所有爬取到的item,避免每次请求都写入Excel,提升效率并避免并发写入问题。 - 爬虫关闭时写入:重写
closed方法,在爬虫结束时先尝试读取现有Excel数据(如果存在),将新数据追加到现有数据后再写入;若文件不存在则直接写入新数据,实现真正的追加效果。
内容的提问来源于stack exchange,提问作者xlmaster
相关产品推荐
相关产品推荐

