Python遍历两组数据条件追加写入CSV的代码问题排查
Python eBay爬取结果CSV写入问题修复方案
核心问题根因
- 表头重复/缺失问题:原逻辑未判断CSV文件状态,直接调用
writeheader()会导致每次运行重复追加表头;直接以读模式打开首次运行的不存在文件还会触发报错。 - 去重逻辑失效问题:原代码使用嵌套循环判断ID,逻辑为「只要和任意一条已存ID不相等就写入」,会导致单条数据重复写入多次;同时
csv.reader是迭代器,遍历一次后就会耗尽,后续结果无法读取已存ID数据,判断完全失效。
修复后完整代码
import csv import os import smtplib from requests_html import HTMLSession SEARCH_TERMS = ['one', 'two'] CSV_PATH = 'ebay-results.csv' FIELD_NAMES = ['Title', 'Link', 'ID'] # 爬取eBay结果 session = HTMLSession() response = session.get('https://www.ebay.com/sch/i.html?_from=R40&_nkw=blink+182&_sacat=0&_sop=10&rt=nc&LH_PrefLoc=2') results = response.html.find('ul.srp-results li.s-item') # 第一步:读取已存在的结果ID,用于去重 existing_result_ids = set() is_file_valid = os.path.exists(CSV_PATH) and os.path.getsize(CSV_PATH) > 0 if is_file_valid: with open(CSV_PATH, 'r', encoding='utf-8', newline='') as csv_file: csv_reader = csv.DictReader(csv_file, fieldnames=FIELD_NAMES) next(csv_reader) # 跳过已有表头 for row in csv_reader: existing_result_ids.add(row['ID']) # 第二步:追加写入新结果 with open(CSV_PATH, 'a', encoding='utf-8', newline='') as csv_file_updated: csv_writer = csv.DictWriter(csv_file_updated, fieldnames=FIELD_NAMES) # 仅当文件为空/不存在时写入表头 if not is_file_valid: csv_writer.writeheader() search_terms = [term.upper() for term in SEARCH_TERMS] for result in results: result_title = result.find('h3.s-item__title', first=True).text.replace('New Listing', '').strip() result_link = result.find('a.s-item__link', first=True).attrs['href'].split('?')[0] result_id = result_link.split('/')[4].split('?')[0] # 先匹配关键词,再判断ID是否已存在,两个条件同时满足才写入 if any(term in result_title.upper() for term in search_terms) and result_id not in existing_result_ids: result_info = { 'Title': result_title, 'Link': result_link, 'ID': result_id } csv_writer.writerow(result_info) # 自行补全send_email函数逻辑 send_email(search_terms, result_link) # 新写入的ID加入集合,避免同批次爬取的重复数据重复写入 existing_result_ids.add(result_id)
关键修改说明
- 表头逻辑:通过文件存在性+文件大小判断是否为首次写入,仅空文件/不存在的文件会自动写入表头,不会出现重复表头问题。
- 去重逻辑:提前将所有已存ID加载到set集合中,判断ID是否存在的时间复杂度为O(1),没有嵌套循环的逻辑错误;新写入的ID会实时加入集合,同批次爬取到的重复内容也不会重复写入。
- 文件操作优化:将读、写操作拆分,先完成所有已存数据的读取再执行追加写入,避免同一文件同时读写的冲突、迭代器耗尽问题;文件打开时指定
newline=''和encoding='utf-8',避免CSV空行、中文乱码问题。
注:代码中
send_email()为原有自定义函数,需自行补全邮件发送逻辑。
内容的提问来源于stack exchange,提问作者Mario Parra
相关产品推荐
相关产品推荐

