电商数据抓取完成,并不代表数据已经可以分析。我曾经处理过一批商品明细:原始文件约有 12.8 万行,团队一开始直接按商品名称统计价格和销量,结果显示某个品类的平均价格只有 18.6 元;把商品 ID、SKU 和抓取时间重新整理后,平均价格变成 46.3 元。差异并不是市场突然变化,而是原始数据把不同规格、重复采集记录和“券后价”混在了一起。对数据分析师来说,抓取只是获得材料,清洗才是把材料变成证据。
这也是我建议初学者优先学习数据清洗,而不是一上来研究复杂爬虫框架的原因。采集技术决定你能不能拿到数据,质量治理决定你拿到的数据能不能支持决策。价格、销量、评价、店铺和 SKU 之间只要有一个关键口径没有统一,后面的看板、报表和分析结论都可能建立在错误的基础上。
很多初学者把数据抓取的完成标准定义为:文件成功下载、行数足够多、字段看起来比较齐全。但在真实项目中,这三个条件远远不够。数据分析真正关心的是:每一行记录代表什么,字段是否有稳定含义,重复记录是否可以解释,缺失值是否能区分业务无值和采集失败。
例如,一行商品记录可能代表一个商品、一个 SKU、一个店铺商品关系,也可能只是某个时间点的页面快照。如果没有先确认记录粒度,那么“商品数量”“平均价格”“店铺销量”这些指标都没有可靠的计算基础。
| 判断维度 | 看似正常的表现 | 真正需要追问的问题 | 不处理的后果 |
|---|---|---|---|
| 完整性 | 大部分字段都有值 | 关键字段的缺失是否集中在某些店铺、类目或时间段 | 样本偏差,结论无法代表整体 |
| 唯一性 | 每行看起来都不一样 | 商品 ID、SKU ID 和抓取时间是否构成合理主键 | 重复统计商品数、销量和评论数 |
| 有效性 | 价格和销量都能看到文字 | 字段能否稳定转换为数值,单位是否一致 | 均值、排序和分组计算失真 |
| 一致性 | 字段名称基本相同 | 不同批次、平台或采集程序是否使用同一口径 | 跨时间、跨来源比较失效 |
| 可追溯性 | 知道数据保存在哪个文件 | 能否还原来源、采集时间和清洗规则 | 出现异常时无法定位原因 |
我的判断标准是:如果一条数据不能被解释、验证和复现,它就只能算原始材料,不能算分析数据。这条标准看起来严格,但能有效避免“先做结论、后补数据质量”的常见返工。

数据清洗的目标不是让每个单元格都填满,也不是把所有异常值删除。它真正要解决的是三个问题:第一,字段能不能被计算;第二,记录之间能不能被正确关联;第三,分析结果能不能被业务人员理解。
比如评分为空,不一定应该填成 0。评分为空可能表示商品没有评价,也可能表示页面没有加载成功,还可能是采集程序没有找到对应节点。把这三种情况全部填成 0,会把“没有数据”伪装成“评分很低”,这不是清洗,而是制造数据。
同一份原始数据,用于不同分析目标时,清洗方式并不相同。做价格带分析时,需要明确展示价、活动价、券后价和 SKU 起售价的区别;做商品趋势分析时,需要保留不同时间的商品快照;做店铺规模分析时,可能只需要按商品 ID 去重,而不是保留每个 SKU。
因此,清洗规则不能脱离业务问题单独设计。最稳妥的顺序是:先写清楚准备回答什么问题,再决定一行数据代表什么,最后才处理格式、缺失和重复。
为了说明问题,下面使用一组脱敏的情景样本。字段结构来自常见的商品抓取任务,数值为演示数据,不代表任何平台的市场统计结果。
| 商品 ID | 商品名称 | 价格 | 销量 | 评分 | 评论数 | 店铺 | 抓取时间 |
|---|---|---|---|---|---|---|---|
| 10086 | 轻薄羽绒服 黑色 | ¥299.00 | 1.2万+ | 4.8 | 3,205 | 甲服饰旗舰店 | 2026-09-01 10:00 |
| 10086 | 轻薄羽绒服 黑色 | 299 | 12000 | 4.8 | 3205 | 甲服饰旗舰店 | 2026/09/01 10:00 |
| 10086-S | 轻薄羽绒服 黑色 S码 | 279-299 | 9800人付款 | 暂无 | , | 甲服饰旗舰店 | 2026-09-01 10:00 |
| 10087 | 保温杯 500ml | 39.9 | 865 | – | 0 | 乙生活馆 | 2026-09-01 10:00 |
| 10088 | 保温杯 500毫升 | ¥39.90 | 865 | 4.7 | 865 | 乙生活馆官方店 | 2026-09-01 10:00 |
这张小表里至少存在六种需要判断的问题:第一、二行可能是完全重复;第三行是 SKU 记录还是商品变体;价格区间是否应该取最低价;“1.2万+”与“9800人付款”是否具有相同统计口径;评分的“暂无”与连字符是否代表同一含义;两个店铺名称是否需要归并。
如果只用表格软件执行“删除重复项”和“替换字符”,很容易把业务含义一并删掉。数据清洗最难的部分往往不是代码,而是判断哪些差异是真差异,哪些差异只是展示形式不同。
假设原始表中有 10 万条记录,其中 2 万条是同一批商品的重复抓取,1.5 万条是 SKU 明细,另有 8000 条价格字段保存的是区间起始价。若直接按行计算平均价格,得到的结果同时受到重复记录、规格结构和价格口径影响。
这时分析师可能会向业务方汇报:“该品类平均售价为 31.8 元。”业务方接着按照这个价格制定选品策略,但真实的商品层中位数可能是 49 元,平均值之所以偏低,是因为低价 SKU 和重复展示记录被过度计入。
在电商分析中,我通常更关注记录粒度、价格分布和中位数,而不是一开始就追求一个看起来精确的平均值。平均数容易被极端价格和重复记录影响,中位数、四分位数以及分价格带商品数量,往往更接近选品和竞品判断的实际需求。

同一个商品在不同时间出现,并不一定是重复数据。价格、库存、销量和评价都可能随时间变化。如果把商品 ID 作为唯一主键,直接保留一条记录,就会丢失趋势分析所需要的历史快照。
但如果完全不去重,同一个商品每天、每小时甚至每次翻页都被重复计入,商品数量和店铺规模又会被放大。解决办法不是简单地“保留最新”或“全部保留”,而是明确分析粒度,例如使用“商品 ID+抓取日期”作为日快照主键,使用“SKU ID+抓取时间”作为明细主键。
我在设计数据表时,通常会把商品主表和历史快照表拆开。商品主表保存相对稳定的名称、品牌、类目和店铺关系;快照表保存某个时间点的价格、销量、库存和评价。这样既能做当前商品分析,也能做变化趋势分析。
价格是电商数据中最容易被“清洗错”的字段。常见展示形式包括“¥39.90”“39.9 元”“29.9-49.9”“券后 24.9 元”“低至 9.9 元”和“到手价 39 元”。这些文字都包含数字,但它们的业务含义并不相同。
如果分析目标是比较商品的最低入门价格,可以提取价格区间下限;如果目标是比较主流成交价格,就不能把“低至”价格直接当作商品实际售价;如果要评估促销力度,则应该同时保留原价、活动价和优惠后价格,而不是覆盖成一个 price 字段。
建议至少保留以下字段:原始价格文本、价格下限、价格上限、价格类型、币种、价格解析状态。原始文本看似多余,实际上是后续争议发生时最重要的审计依据。
“1.2万+”“3000人付款”“月销 5000+”都可以用于排序或相对比较,但它们未必是同一个统计口径。“人付款”可能是页面展示口径,“月销”带有时间窗口,“1.2万+”还存在四舍五入或区间表达。
清洗时可以把文本转换为数值,但必须额外增加销量口径字段。例如将“1.2万+”转换为 12000 时,保存 unit_type=万、source_text=1.2万+、is_approximate=true。这样后续使用者知道这个数值是展示值的标准化结果,而不是精确订单量。
数值化不等于事实化。这是电商数据清洗中非常重要的边界。把字符串转成整数,只解决了计算问题,没有自动解决统计口径问题。
评分为空,可能是新商品没有评分,也可能是页面没有加载成功。评论数为 0,可能代表页面明确显示零评论,也可能是程序把“暂无”错误转换成了 0。两者在业务上不能混为一谈。
我通常会设置三个字段:标准化数值、原始文本和字段状态。字段状态可以使用“已解析”“业务无值”“页面未展示”“解析失败”“待人工核验”等枚举值。这样的设计比单纯填充空值更适合长期项目。
| 原始内容 | 标准数值 | 字段状态 | 推荐解释 |
|---|---|---|---|
| 4.8 | 4.8 | 已解析 | 页面存在可识别评分 |
| 暂无 | 空值 | 业务无值或页面未展示 | 需要结合页面结构进一步确认 |
| , | 空值 | 待核验 | 不能直接推断为零分 |
| 4.8分 | 4.8 | 已解析 | 清除单位后保留数值 |
| 异常字符 | 空值 | 解析失败 | 进入异常队列,不应静默丢弃 |
同一款商品可能有不同颜色、尺寸、容量或套餐。页面上看到的商品标题相同,不代表它们在价格、库存和销量层面可以直接合并。相反,标题略有不同,也不一定是不同商品,因为商家可能加入了促销词、季节词或搜索词。
处理这类数据时,优先使用稳定的商品 ID、SKU ID、店铺 ID,而不是只依赖商品名称。没有稳定 ID 时,才考虑使用“店铺+标题清洗结果+规格”等组合字段,并把匹配结果标记为自动匹配或人工确认。
如果业务问题是“有多少款商品”,应在商品层去重;如果问题是“不同规格的价格差异”,就必须保留 SKU 层;如果问题是“某店铺的商品结构”,则要先确定店铺、商品和 SKU 的层级关系。
“乙生活馆”“乙生活馆官方店”“乙生活馆旗舰店”可能属于同一个经营主体,也可能是不同渠道店铺。自动把名称包含相同关键词的记录归并,存在误合并风险;完全不归并,又会把一个经营主体拆成多个对象。
比较稳妥的方法是建立名称映射表,至少保存原始名称、标准名称、店铺 ID、归并依据和确认状态。第一次可以通过规则生成候选匹配,之后由业务人员确认,而不是直接覆盖原始名称。
“2026-09-01”“2026/9/1”“2026 年 9 月 1 日 10:00”都可以转换成标准时间,但转换时还要判断时间粒度。日度采集数据不应被伪装成小时级数据,页面显示日期也不代表商品实际发生变化的时间。
做趋势分析时,建议同时保留抓取开始时间、抓取结束时间、标准日期和批次编号。对于跨来源数据,还应注明时区和采集窗口,避免把不同时间的页面状态放在同一条时间线上比较。

这是整个清洗流程的起点。如果一行代表商品快照,那么商品 ID+抓取日期可能是主键;如果一行代表 SKU 快照,就需要 SKU ID+抓取时间;如果一行代表店铺在某个类目中的统计结果,主键又会变成店铺 ID+类目 ID+统计日期。
我会在项目开始前写一段“数据粒度声明”,用一句话说明每行的业务含义。例如:“本表每行代表某店铺某 SKU 在一个自然日内最近一次成功采集的页面状态。”这句话能够约束后续的去重、汇总和指标计算。
如果无法写出这句话,说明数据模型还没有想清楚,此时不应该急着做报表。报表越早上线,后面返工的成本越高。
整行去重只适合处理完全相同的复制记录,不能解决业务重复。商品名称、价格、销量和评论数完全相同,并不代表记录应该删除;如果抓取时间不同,它们可能是有效的历史快照。
主键设计通常有三种思路。第一种是实体主键,例如商品 ID,适合当前商品清单;第二种是实体加时间,例如商品 ID+日期,适合趋势快照;第三种是层级组合主键,例如店铺 ID+商品 ID+SKU ID+日期,适合多层级明细。
主键一旦确定,就应该把违反主键唯一性的记录输出到异常表,而不是静默覆盖。异常表可以帮助分析师判断是重复抓取、ID 变化、数据拼接错误,还是业务上确实存在多个版本。
为了避免清洗规则混乱,我通常会把字段分成四类。第一类是标识字段,例如商品 ID、SKU ID 和店铺 ID;第二类是维度字段,例如品牌、类目、店铺名称;第三类是度量字段,例如价格、销量、评论数;第四类是过程字段,例如抓取时间、来源 URL 和处理批次。
| 字段类型 | 核心目标 | 常见处理动作 | 不建议做的事 |
|---|---|---|---|
| 标识字段 | 稳定、唯一、可关联 | 去除无意义空格,检查重复和空值 | 随意截断或用标题替代稳定 ID |
| 维度字段 | 名称和层级统一 | 标准化映射,保留原始值 | 未经确认合并相似名称 |
| 度量字段 | 可计算、单位明确 | 数值转换,保留口径和解析状态 | 把缺失值全部填成 0 |
| 过程字段 | 可追溯、可复盘 | 统一时间格式,记录批次和来源 | 清洗后删除原始来源信息 |
质量规则可以分为完整性、唯一性、有效性、一致性和及时性五类。比如商品 ID 不应为空,价格应能解析成非负数,评分应处于业务允许范围,抓取日期应落在采集任务时间窗口内。
规则不一定要一开始就很复杂。初学者可以先建立十条最小规则,再根据异常情况逐步增加。最重要的是每条规则都要有名称、判断条件、异常数量和处理动作,不能只在脑中记住“这批数据好像有问题”。
质量规则示例:
这里的阈值不应照搬其他项目。对价格分析来说,价格字段缺失率可能必须很低;对店铺名称分析来说,少量名称缺失可以进入待补充队列。质量阈值必须服从分析目标,而不是追求一个看起来统一的百分比。

原始数据应该是只读文件或只读数据表,保存来源、采集时间、文件名、任务编号和哈希信息。清洗过程使用副本,标准化结果写入新的版本。这样做的目的不是形式上的规范,而是让你在发现错误时能够重新处理。
例如,某次清洗把“暂无评论”错误转换成了 0,如果原始文本已经被覆盖,后续很难判断这 0 是页面真实展示还是程序生成。保留原始字段,可以把问题定位到解析规则,而不是反复猜测。
同一个字段不能同时出现 price、商品价格、售价和 price_text 这类混乱命名。建议先制定字段字典,写清楚字段名称、中文含义、数据类型、允许空值、单位和来源。
| 标准字段 | 数据类型 | 单位 | 是否允许为空 | 说明 |
|---|---|---|---|---|
| product_id | 字符串 | 无 | 否 | 商品稳定标识,不建议转成整数以免丢失前导字符 |
| price_min | 数值 | 元 | 是 | 价格区间下限,必须配合 price_type 使用 |
| sales_value | 数值 | 展示口径对应的数量 | 是 | 不等同于严格订单量 |
| sales_text | 字符串 | 无 | 否 | 保留页面原始销量文本 |
| snapshot_date | 日期 | 自然日 | 否 | 用于商品历史快照和趋势分析 |
空值也要统一。空字符串、NULL、“暂无”、“未显示”和“-”不能在系统中无限制混用。建议先保留 raw_value,再根据规则生成 clean_value 和 value_status,避免把不同原因的空值压缩成一个结果。
文本清洗通常包括去除首尾空格、统一全角半角字符、清理不可见字符、标准化单位和处理常见符号。对于商品标题,还可以去除部分营销词,但不建议直接覆盖原始标题,因为营销词有时正是搜索词和卖点分析的重要素材。
一个稳妥的字段设计是同时保留 product_name_raw 和 product_name_normalized。前者用于追溯和关键词研究,后者用于去重和分类。两者承担不同任务,不应只保留其中一个。
不要把所有无法转换的值直接设为 0。更好的做法是将转换结果、原始文本和解析状态同时输出。状态可以包括 parsed、range、approximate、missing、failed 等,中文项目也可以使用对应的中文枚举。
示例字段:
price_text = "券后 29.9-39.9 元"
price_min = 29.9
price_max = 39.9
price_type = "券后价区间"
parse_status = "已解析"
is_approximate = false
如果价格文本是“低至 9.9 元”,可以记录 price_min=9.9,但必须把 price_type 标记为“最低展示价”,不能在报表里把它和单一成交价混合计算。
缺失值可以按照业务含义分为四类:业务上不存在、页面没有展示、采集程序失败和字段解析失败。第一类通常可以保留空值;第二类需要记录页面状态;第三类要回到采集日志排查;第四类则应修正规则后重新解析。
只有在确认某类缺失会影响目标分析,而且无法通过补采或合理推断修复时,才考虑删除。对于价格趋势这类对字段要求较高的分析,可以单独生成“价格完整样本”;对于商品结构分析,则不必因为评分为空而删除整个商品。
完全重复是指主键、字段值和抓取时间都相同的记录,可以通过规则去除。业务重复则需要判断记录粒度,例如同一商品不同 SKU、同一商品不同时间快照、同一店铺不同渠道页面,都不能仅凭标题或部分字段直接删除。
我建议把去重结果分成三类:确认删除、确认保留和待人工判断。待判断记录不能混进正式分析表,但也不应该直接丢弃,可以进入异常队列,后续用于完善匹配规则。
价格为 0 可能是免费商品、赠品或解析失败;价格为 99999 可能是高端商品,也可能是把商品编号误读成价格。评分为 0 可能是无评分,也可能是字段错误。异常检测只能发现需要关注的记录,不能自动证明记录一定错误。
常见的处理顺序是:先做格式规则,再做范围规则,最后结合分组和时间序列判断。例如某店铺所有商品价格都在 30 至 80 元,某一条突然出现 0.03 元,就值得核查;但如果这是一个真实的促销活动,直接删除反而会损失业务信息。

如果只有几百到几千行数据,使用电子表格进行抽样、筛选、透视和基础清洗完全可以。这个阶段最重要的不是工具性能,而是学会记录字段字典、主键定义和异常处理过程。
表格工具适合快速查看原始数据、确认页面展示形式和与业务人员共同核验。但当数据需要多次重复处理,或者数据量超过人工容易控制的范围时,纯手工操作就会出现版本混乱、步骤不可复现和误删记录等问题。
Python 配合 pandas 适合处理 CSV、Excel、JSON 等文件,也适合编写价格解析、销量单位转换、名称标准化和异常标记规则。它的价值不是“自动化一切”,而是把人工做过一次的清洗动作变成可重复执行的程序。
import pandas as pd
import re
df = pd.read_csv("product_raw.csv", dtype={"product_id": "string"})
df["price_text"] = df["price"].astype("string").str.strip()
def parse_sales(value):
if pd.isna(value):
return pd.Series([None, "缺失"])
text = str(value).replace(",", "").strip()
match = re.search(r"([\d.]+)\s*万", text)
if match:
return pd.Series([float(match.group(1)) * 10000, "近似展示值"])
match = re.search(r"([\d.]+)", text)
if match:
return pd.Series([float(match.group(1)), "已解析"])
return pd.Series([None, "解析失败"])
df[["sales_value", "sales_status"]] = df["sales_text"].apply(parse_sales)
df["snapshot_date"] = pd.to_datetime(
df["snapshot_time"], errors="coerce"
).dt.date
duplicate_count = df.duplicated(
subset=["product_id", "snapshot_date"], keep="first"
).sum()
print("按商品和日期识别的重复记录数:", duplicate_count)示例代码只展示思路,真实项目还需要根据数据源增加价格区间、促销价、店铺映射和 SKU 关系等规则。尤其要注意:代码可以执行规则,但不能替代对业务粒度的判断。
当数据已经进入数据库,SQL 往往比反复导出文件更适合做标准化处理。它适合筛选空值、识别重复主键、聚合商品和店铺指标,也便于把质量规则嵌入每日处理流程。
-- 检查商品日快照主键是否重复 SELECT product_id, snapshot_date, COUNT(*) AS record_count FROM product_snapshot GROUP BY product_id, snapshot_date HAVING COUNT(*) > 1; -- 检查关键字段缺失 SELECT COUNT(*) AS total_rows, SUM(CASE WHEN product_id IS NULL THEN 1 ELSE 0 END) AS missing_product_id, SUM(CASE WHEN price_value IS NULL THEN 1 ELSE 0 END) AS missing_price, SUM(CASE WHEN snapshot_date IS NULL THEN 1 ELSE 0 END) AS missing_snapshot_date FROM product_snapshot;
当团队已经有相对稳定的数据表,并且需要把商品、店铺、价格、销量和时间字段连接起来做可视化分析时,可以考虑使用九数云这类数据分析工具。它更适合作为清洗结果的分析层、业务验证层和可视化层,而不是替代所有采集与底层治理工作。
在实际使用逻辑上,我会把职责拆成三层:第一层保留原始采集数据;第二层用 Python 或 SQL 完成字段标准化、主键处理和异常标记;第三层将标准表接入九数云,制作价格分布、店铺对比、商品趋势和质量监控视图。
这样做的好处是,业务人员可以在图表中快速发现异常。例如某个店铺商品数量突然翻倍、某个价格带的商品突然消失、某批次销量全部变成 0,都可以通过看板反馈给数据处理环节。分析工具最有价值的地方,不是替你决定如何清洗,而是帮助你发现清洗规则是否产生了不合理结果。
如果团队规模较小,数据量不大,也可以直接使用九数云完成部分字段整理、汇总和可视化。但涉及复杂文本解析、批量文件合并、主键重构和高频自动任务时,仍建议在进入分析工具之前完成程序化治理。
| 工具方式 | 更适合的任务 | 优势 | 局限 | 推荐使用阶段 |
|---|---|---|---|---|
| 电子表格 | 抽样查看、简单替换、快速核验 | 上手快,业务人员容易参与 | 步骤难复现,规模扩大后易出错 | 探索期和小样本验证 |
| Python | 批量文件、文本解析、自定义规则 | 灵活,可重复执行 | 需要编程基础,规则需维护 | 中小规模和复杂清洗 |
| SQL | 去重、聚合、质量检查、标准表构建 | 适合数据库和稳定流程 | 复杂文本处理不如 Python 直观 | 数据入库后的治理 |
| 九数云 | 可视化分析、指标验证、业务看板 | 降低分析和共享门槛,便于反馈异常 | 不应替代底层采集和复杂数据工程 | 清洗后的分析与监控层 |

很多团队的验收方式是打开仪表板,看几个数字是否“像真的”。这种方式只能发现非常明显的错误,无法发现重复计算、缺失集中和口径漂移。更稳妥的方法是先生成数据质量报告,再进入业务分析。
建议至少检查以下指标:关键字段缺失率、主键重复率、数值解析成功率、异常值比例、来源完整率、采集时间覆盖率以及清洗前后记录变化率。
这些指标不需要全部达到 100%。例如销量展示值可能天然是近似值,评分在新商品中可能缺失。关键在于每个指标都要有解释,业务方知道哪些问题可接受,哪些问题会阻止数据进入正式分析。
我通常会随机抽取三类样本:正常记录、异常记录和边界记录。正常记录用于确认常规解析没有被破坏;异常记录用于检查规则是否按预期拦截;边界记录则包括价格区间、缺失评分、同名商品和不同规格商品。
如果数据来源允许,应将样本与原始页面、授权接口返回值或业务维护表进行比对。抽样不需要覆盖所有记录,但必须覆盖高风险字段和高频异常类型。
清洗结果是否合理,可以从四个层面比较:记录数变化、字段缺失变化、分布变化和业务排名变化。如果记录数减少 20%,但没有任何删除原因记录,这是风险;如果平均价格变化很大,但中位数和价格带结构更稳定,可能说明清洗确实排除了重复或异常影响。
| 对比项目 | 清洗前 | 清洗后 | 需要追问的问题 |
|---|---|---|---|
| 商品记录数 | 128000 行 | 92100 行 | 减少的 35900 行分别是什么原因 |
| 价格解析成功率 | 86.4% | 97.1% | 新增成功解析的规则是否经过抽样验证 |
| 商品日快照重复率 | 12.8% | 0.7% | 剩余重复是否属于特殊 SKU 或多来源记录 |
| 价格中位数 | 31.8 元 | 49.0 元 | 变化是否由重复低价 SKU 和价格口径混合造成 |
| 关键来源完整率 | 91.2% | 99.3% | 缺失来源记录是否已进入补采或异常队列 |
表中的数值为情景模拟,重点是展示验收方法。真正项目中,不应只报一个“清洗后数据更干净”的结论,而应同时报告清洗动作、保留率、异常率和统计结果变化。

技术规则通过,不代表业务结论合理。比如某店铺商品数在一天内增长 300%,可能是店铺真实上新,也可能是分页重复、类目扩展或 ID 解析错误。某个价格带销量突然全部归零,也可能是页面展示规则发生变化。
业务合理性检查可以从排名、分布和变化三个方向入手。排名看是否被单个异常值支配,分布看是否出现不自然的断层,变化看是否与采集批次、页面改版或业务活动相吻合。
不要先追求搭建复杂采集系统。建议找一份规模可控的商品数据,先完成字段字典、主键定义、价格清洗、销量转换、重复识别和质量报告。哪怕只有 5000 行,只要能完整走通流程,也比下载几十万行数据后无法解释更有价值。
学习顺序可以是:先用表格理解数据结构,再用 Python 重复清洗过程,最后用 SQL 完成入库检查和聚合。等你能解释每一条删除规则,再考虑自动化和可视化。
优先治理价格口径和商品层级。不要把 SKU 起售价、券后价、活动价和页面主展示价直接混在一起。建议同时输出价格下限、价格上限、价格类型和解析状态,并使用中位数、四分位数和价格带分布辅助判断。
取舍在于:保留更多价格字段会增加模型复杂度,但能避免把不同价格口径压成一个数字。若只是做粗略市场扫描,可以使用价格下限,但报告中必须注明“最低展示价”,不能把它表述成普遍成交价格。
先确认销量字段的时间口径和展示规则,再考虑排序。对“月销”“累计销量”“付款人数”和“销量估计值”应分开建字段。无法确认口径时,可以做相对排名,但不要把排序结果表述为精确销售额。
取舍在于:严格保留口径会减少可比较样本,但结论更可信;强行统一可以扩大样本覆盖,但会引入不可见的偏差。我的建议是宁愿保留“可比较样本”和“全部样本”两套结果,也不要让一个看似完整的排行榜掩盖口径差异。
必须保留抓取时间和采集批次,并按商品 ID+时间粒度建立快照主键。不要把不同日期的数据简单合并为一行,也不要用当前商品状态回填过去的历史记录。
取舍在于:保存历史快照会增加存储成本和清洗复杂度,但能支持价格变化、评价变化和上下架观察。如果业务只关心当前商品清单,可以保留商品主表,不必为所有字段维护完整历史。
先建立店铺和品牌映射表,保留原始名称、标准名称、ID 和确认状态。对无法确认是否属于同一主体的名称,不要为了让图表整齐而强行归并。
取舍在于:保守归并会导致同一主体被拆成多个对象,激进归并则可能把不同经营主体错误合并。前者影响规模统计,后者会直接改变竞争判断。对于重要客户或重点店铺,人工确认的成本通常值得投入。
建议先准备稳定的标准表和字段说明,再连接分析工具。最少应包含商品主表、商品快照表、店铺维度表和质量检查表。这样既能制作业务看板,也能让使用者看到数据更新时间、样本范围和异常比例。
在九数云中可以围绕三个方向设计看板:第一是业务分析,例如价格带、商品数量、店铺分布和趋势;第二是数据质量,例如缺失率、重复率、解析失败率和批次变化;第三是异常反馈,例如某批次价格突然偏移、某店铺记录暴增和关键来源中断。
取舍在于:看板越丰富,业务理解越直观,但维护成本也越高。初期不建议一次性制作几十张图,优先保留能回答核心问题的页面,并把质量监控放在业务看板旁边,避免使用者只看到结论而看不到数据条件。

这是最常见也最危险的快捷处理。零代表一个明确的数值状态,而空值代表信息缺失或业务不适用。把评分空值填成零,会让商品进入低评分区间;把销量空值填成零,会让采集失败的商品看起来没有销量。
除非业务方明确规定空值就是零,否则应保留空值,并增加缺失原因字段。对于需要计算的场景,可以分别输出“全部商品”和“字段完整商品”两套统计。
商品标题不是稳定主键。相同标题可能属于不同店铺、不同规格或不同活动页面;不同标题也可能是同一商品加入了季节词、促销词和关键词扩展。
标题清洗可以作为辅助匹配手段,但必须保留匹配置信度和确认状态。对高价值分析,稳定 ID 和店铺关系应优先于标题相似度。
只保留清洗后的数值,看起来表格更整齐,但会损失追溯能力。尤其是销量和价格这类带展示口径的字段,后续经常会有人追问“这个数是怎么来的”。没有原始文本,就无法说明转换依据。
推荐保留 raw 字段、clean 字段和 status 字段。存储空间通常不是最大的成本,无法解释错误结果才是。
平均值很容易被极端值、重复记录和低价 SKU 拉动。报告中至少要同时查看中位数、四分位数、价格带分布和样本量。做店铺比较时,还应关注每个店铺的商品覆盖数量,否则小样本店铺可能因为一两个商品的极端值排名靠前。
电商页面是动态的,商品、价格、库存、评价和促销状态都会变化。一次抓取只能说明某个时间窗口内的观察结果,不能直接代表长期市场情况。
发布分析结论时,应明确采集时间、数据来源、样本筛选条件和指标口径。若要判断趋势,至少需要多个时间点,并保证各批次的采集条件尽量一致。
数据抓取应优先使用公开页面、官方接口、授权数据或合法导出渠道。不要把绕过登录、验证码、访问控制或技术防护当作数据分析入门内容,也不要采集与分析目的无关的个人信息。
实际使用前,应核对数据来源的服务条款、访问规则和适用法律要求。对外展示时要控制频率、做好脱敏,并注明数据来源和采集时间。数据清洗的专业性不仅体现在字段处理上,也体现在对数据使用边界的尊重上。
先写下准备回答的三个业务问题,例如“不同价格带的商品数量如何分布”“不同店铺的商品结构有什么差异”“某类商品价格是否发生变化”。然后为每个问题定义一行记录代表什么,以及需要哪些字段。
列出所有字段的名称、类型、单位、来源、是否允许为空和处理规则。先写十条最重要的质量检查,包括主键为空、主键重复、价格不能解析、评分越界、抓取时间缺失等。
不要追求一次性处理所有异常。先完成字段名统一、文本清理、日期转换、基础数值转换和完全重复识别。所有无法确定的问题进入异常队列,不要悄悄删除。
确认商品主表、SKU 明细和店铺维度之间的关联方式。对于没有稳定 ID 的记录,使用组合键并保留匹配依据。此时不要急着制作排行榜,先确保商品数量和店铺数量的统计对象正确。
比较记录数、缺失率、重复率、价格分布和销量分布。随机抽查正常、异常和边界样本,确认清洗规则没有误删有效记录,也没有把明显错误放进标准表。
当同样的清洗动作出现第二次,就应该考虑程序化。Python 适合处理文本和批量文件,SQL 适合入库、去重和聚合,九数云适合把标准数据转成业务可读的分析和质量看板。工具的组合应由任务决定,而不是由流行程度决定。

电商数据抓取的真正难点,往往不在于把网页内容保存下来,而在于回答几个看似基础、实际上决定结论可信度的问题:一行记录代表什么,商品和 SKU 如何区分,价格到底是哪一种价格,销量是否具有相同口径,缺失值究竟意味着什么,重复记录为什么重复。
我最想强调的独特观点是:数据清洗不是把异常值全部删除,而是把每一条记录放回正确的业务语境中。价格区间不一定是错误,缺失评分不一定是零值,同一商品不同日期不一定是重复,同名商品也不一定属于同一个实体。
如果你刚开始做电商数据分析,下一步不要先寻找“最强爬虫工具”。先拿一份真实或脱敏的商品数据,完成四件事:写出数据粒度声明、建立字段字典、定义十条质量规则、制作清洗前后对比报告。完成这四件事,你就已经从“会拿数据”迈向了“会治理数据”。
当数据规模扩大后,再根据实际需要引入 Python、SQL 和九数云等工具,把清洗规则变成可复用流程,把质量检查变成持续监控。最终,优秀的数据分析师不是最会堆砌图表的人,而是能够清楚说明:这些数据从哪里来、经过了什么处理、哪些地方仍有限制,以及业务方可以在什么范围内相信它。


读者评论
文章把“抓到数据”和“数据可分析”区分得很清楚,尤其是记录粒度、主键和时间快照这几个问题,对刚接触电商数据清洗的人很有参考价值。
价格字段的例子比较贴近实际。“券后价”“低至价”和价格区间不能直接混成一个数,保留原始文本和解析状态的做法也方便后续核查。
文中关于缺失值的分析很客观,评分为空不应简单填成0这一点容易被忽视。将业务无值、页面未展示和解析失败分开,确实能减少误判。
用平均价格与中位数对比说明重复记录和低价SKU的影响,比较有说服力。不过实际项目中还需要结合平台口径和样本范围验证规则。
文章更强调业务定义而不是单纯写清洗代码,这个思路适合入门者。商品主表与历史快照表拆分的建议,也有助于兼顾当前分析和趋势分析。