You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 16:33:16