kp-011
数据清洗与持久化:CSV、SQLite 与 Parquet
前置知识
本文基于模型知识整理,建议核对官方文档(见 参考资料)。
一句话定义
清洗把「网页上的人类可读值」变成「机器可算的字段」,持久化则按用途选择 CSV(交换)、JSONL(流式落盘)、SQLite(查询)或 Parquet(分析)。
为什么重要
「¥1,299.00」存成字符串,kp-027 的价格分析就寸步难行。采集脚本的价值不在于抓了多少,而在于落库的数据能直接被查询与计算;清洗是采集与挖掘(kp-024)之间的合同边界。
前置知识
kp-010(有结构化产出);pandas 基础用法。
核心概念
- 类型规整:金额→float、数量→int、时间→ISO 8601、布尔→0/1。
- 单位剥离:货币符号、千分位、单位后缀("万"、"kg")。
- 空值语义:区分「页面没显示」「接口返回 null」「解析失败」三种空。
- 存储选型:CSV 通用可读;JSONL 追加友好、保字段灵活;SQLite 单文件可 SQL 查询;Parquet 列存压缩、分析快。
原理与机制
清洗函数模板(与采集代码解耦,可独立单测):
import re
from datetime import datetime
PRICE_RE = re.compile(r"[-+]?\d[\d,]*\.?\d*")
def clean_price(raw: str | None) -> float | None:
if not raw:
return None
m = PRICE_RE.search(raw.replace(",", ","))
return float(m.group().replace(",", "")) if m else None
def clean_time(raw: str | None) -> str | None:
if not raw:
return None
for fmt in ("%Y-%m-%d %H:%M", "%Y年%m月%d日", "%Y-%m-%d"):
try:
return datetime.strptime(raw.strip(), fmt).isoformat()
except ValueError:
continue
return None # 统一失败语义,而不是抛异常中断全量任务
存储选型对照:
CSV 人读/交换, 类型全丢失, Excel 打开中文需 utf-8-sig
JSONL 追加写入/流式, 字段可演化, 但查询要全量扫描
SQLite 单文件 + SQL, 适合 < 10GB 采集库, WHERE/JOIN/GROUP BY 随手可用
Parquet 列存 + 压缩, pandas/polars 读取极快, 适合交给 kp-027~029 分析
落库最小示例(采集脚本里只做「收集 + 批量写」):
import sqlite3
def save(items):
conn = sqlite3.connect("data.db")
conn.executemany(
"INSERT OR REPLACE INTO products(id,title,price,crawled_at) VALUES(?,?,?,?)",
[(it["id"], it["title"], it["price"], it["crawled_at"]) for it in items],
)
conn.commit(); conn.close()
实例或案例
电商价格监控的库表设计:prices(sku_id, ts, price, source) 每条价格一行(长表),而非「每个 SKU 一列」——长表天然支持 kp-027 的按时间聚合与对比分析。这是「为下游查询设计 schema」的直接体现。
常见误区
- 误区一:CSV 乱码。 Windows Excel 打开 UTF-8 CSV 全是乱码;导出时指定
encoding="utf-8-sig"(带 BOM)。 - 误区二:在采集循环里塞满清洗逻辑。 抓取与清洗耦合导致重跑成本高;正确姿势是先原样落盘(原始层),清洗作为独立可重跑步骤(见 kp-025)。
- 误区三:所有空值都填 0。 「没抓到价格」填 0 会让均价分析严重失真;空就是空,让分析层决定如何处理。
自测题
- 为什么价格字段必须转 float 而不是存字符串?
答:字符串无法参与聚合比较排序,下游时序与统计会全部失败;「¥1,299.00」需剥离符号千分位。
- 四种存储各自的适用场景?
答:CSV 交换、JSONL 流式追加、SQLite 单机查询、Parquet 列式分析。
- 采集层与清洗层为什么要分离?
答:原始数据只落一次,清洗规则可反复迭代重跑;且采集崩溃不影响已清洗数据,回溯成本最低。
与其他知识点的关系
kp-025 把本篇的清洗函数扩成质量管线;kp-024 定义了层间契约;kp-027/029 消费本篇产出的规整数据。
延伸阅读
pandas 官方「io」章节(read_csv/to_sql);SQLite 官方文档的数据类型一节。