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

循环生成字典键动态变化,Python爬虫如何正确将数据写入CSV文件

问题原因

你目前的代码运行出错的核心原因是:

  1. csv.DictWriter初始化时指定的fieldnames必须和CSV文件已有的表头完全一致,你每次都传入当前页数据的键,和原有表头不匹配时就会抛出异常
  2. CSV本身是固定表头的结构化格式,创建后无法直接追加新列,新增列需要重写整个文件保证所有行的字段对齐

解决方案

根据你的爬取场景可以选择两种不同的处理方案:

方案1:先全量采集字段再写入(推荐,性能更高)

如果可以提前遍历所有页面、收集到所有可能出现的表头字段,再统一写入数据是最稳妥的方案,不会有频繁读写文件的性能损耗。
示例代码:

import csv
import os
from bs4 import BeautifulSoup

# 第一步:遍历所有页面收集全量表头
all_fields = set()
# 替换为你遍历所有页面的逻辑
for page in all_site_pages:
    trs = BeautifulSoup(page.content, 'lxml').find_all('tr')
    for tr in trs:
        field_name = tr.find_all('td')[0].text.strip()
        all_fields.add(field_name)
# 可手动排序all_fields保证表头顺序符合预期
all_fields = list(all_fields)

# 第二步:统一提取数据写入CSV
with open('file.csv', 'w', newline='', encoding='utf-8') as f:
    # restval参数指定缺失字段填充空值,extrasaction参数忽略多余字段避免报错
    wr = csv.DictWriter(f, fieldnames=all_fields, restval='', extrasaction='ignore')
    wr.writeheader()
    for page in all_site_pages:
        trs = BeautifulSoup(page.content, 'lxml').find_all('tr')
        data = {}
        for tr in trs:
            tds = tr.find_all('td')
            data[tds[0].text.strip()] = tds[1].text.strip()
        wr.writerow(data)

方案2:动态扩展表头(适合增量爬取场景)

如果是增量爬取、无法提前遍历所有页面,可以每次写入前读取已有表头,合并新字段后重写整个CSV。
示例代码:

import csv
import os

def append_to_csv(new_data):
    file_path = 'file.csv'
    # 文件不存在直接创建写入
    if not os.path.exists(file_path):
        with open(file_path, 'w', newline='', encoding='utf-8') as f:
            wr = csv.DictWriter(f, fieldnames=new_data.keys(), restval='', extrasaction='ignore')
            wr.writeheader()
            wr.writerow(new_data)
        return
    
    # 文件已存在,读取旧表头和旧数据
    with open(file_path, 'r', encoding='utf-8') as f:
        reader = csv.DictReader(f)
        old_fields = reader.fieldnames
        old_rows = list(reader)
    
    # 合并表头,新字段默认追加到表头末尾
    new_fields = old_fields.copy()
    for key in new_data.keys():
        if key not in new_fields:
            new_fields.append(key)
    
    # 重写整个CSV,旧行自动填充新增字段的空值
    with open(file_path, 'w', newline='', encoding='utf-8') as f:
        wr = csv.DictWriter(f, fieldnames=new_fields, restval='', extrasaction='ignore')
        wr.writeheader()
        wr.writerows(old_rows)
        wr.writerow(new_data)

注意:该方案每次写入都需要读写全量CSV,数据量大时性能会明显下降,仅适合小数据量的增量爬取场景

内容的提问来源于stack exchange,提问作者Username

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:30:05