如何使用Python写入字段数量不固定的CSV文件
实现方案
核心思路
不同商品的参数列不统一,本质是需要先确定所有要写入的表头字段,再将每个商品的参数和表头做映射,缺失的参数自动填充空值即可。
场景1:小规模爬取(可先爬完所有数据再写入)
这是兼容性最高的方案,不会出现动态加列的适配问题:
- 先把所有爬取到的商品数据存在列表中,每个商品存为字典结构,比如
{"商品名称":"XX","价格":99,"屏幕尺寸":"6.7英寸","电池容量":"5000mAh"},允许不同商品的字典key存在差异 - 遍历所有商品字典,收集所有出现过的key并去重,作为CSV的完整表头,你可以把商品名称、价格这类固定字段调整到表头前列
- 用Python的
csv.DictWriter写入,指定缺失字段默认填充空值即可
示例代码:
import csv # all_products为你爬取到的所有商品字典列表 all_products = [ {"商品名称":"手机A","价格":2999,"屏幕尺寸":"6.7英寸","电池容量":"5000mAh"}, {"商品名称":"笔记本B","价格":5999,"屏幕尺寸":"16英寸","显卡":"RTX4060","内存":"16G"}, {"商品名称":"耳机C","价格":399,"佩戴方式":"入耳式","续航时间":"24小时"} ] # 收集所有表头字段 fieldnames = set() for product in all_products: fieldnames.update(product.keys()) # 将固定字段放在表头前侧,可根据需求调整 fixed_fields = ["商品名称","描述","价格"] fieldnames = fixed_fields + [f for f in fieldnames if f not in fixed_fields] # 写入CSV with open("products.csv", "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, restval="") writer.writeheader() writer.writerows(all_products)
注:用utf-8-sig编码是为了兼容Windows系统下Excel打开不乱码,restval参数可自定义缺失字段的填充值。
场景2:大规模爬取(需要边爬边写,无法等全部爬完)
这种场景需要支持动态追加新的参数列,实现逻辑是每次爬取到新商品时,先检查是否存在未收录的参数key,如果有就更新表头,重写已有数据后再追加新行。
示例代码:
import csv import os CSV_SAVE_PATH = "products.csv" # 初始化表头,先填入固定字段 fieldnames = ["商品名称","描述","价格"] # 缓存已写入的商品数据,用于更新表头后重写 saved_products = [] def save_single_product(product): global fieldnames # 检查是否有新增参数字段 new_fields = [k for k in product.keys() if k not in fieldnames] if new_fields: # 更新表头 fieldnames.extend(new_fields) # 重写整个CSV的表头和已有数据 with open(CSV_SAVE_PATH, "w", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, restval="") writer.writeheader() writer.writerows(saved_products) # 追加当前爬取的商品数据 with open(CSV_SAVE_PATH, "a", newline="", encoding="utf-8-sig") as f: writer = csv.DictWriter(f, fieldnames=fieldnames, restval="") # 首次写入时先写表头 if os.path.getsize(CSV_SAVE_PATH) == 0: writer.writeheader() writer.writerow(product) saved_products.append(product) # 调用示例:每爬取到一个商品就调用一次方法 save_single_product({"商品名称":"手机A","价格":2999,"屏幕尺寸":"6.7英寸"}) save_single_product({"商品名称":"笔记本B","价格":5999,"显卡":"RTX4060"})
注:如果爬取量级极大,每次重写CSV性能损耗较高,可以先把数据存为临时jsonl格式,全部爬完后再统一转成CSV,效率会高很多。
注意事项
- 爬取规格参数时要统一key的命名,避免出现
屏幕尺寸和屏幕大小这类同含义不同命名的key,否则会导致参数错列 - csv模块会自动转义参数值中的逗号、换行符等特殊字符,不需要额外处理
内容的提问来源于stack exchange,提问作者koolaa12
相关产品推荐
相关产品推荐

