电商数据抓取项目里,最容易被低估的并不是“能不能把商品抓下来”,而是抓下来的 10 万条记录究竟代表多少个真实商品。我在参与选品数据流程设计时遇到过一个典型场景:搜索页、类目页、店铺页和推荐位合计返回 10,000 条记录,清洗后只剩 6,800 个商品实体;如果直接按原始行统计,商品数量、竞争度、价格区间和评论表现都会被系统性放大。减少重复数据的关键,不是简单删除重复行,而是先定义商品层级,再让采集、去重、更新和分析使用同一套业务口径。
电商数据抓取:开发人员流程优化:选品研究怎样减少重复数据多
开发人员说“数据重复”,通常指的是数据库中出现了多行相似记录。但在选品研究中,相似不等于重复。相同商品的不同规格、不同店铺、不同时间快照,都可能需要保留。如果一开始就用标题或页面 URL 做删除规则,往往会把有价值的数据误删。
| 重复类型 | 典型表现 | 是否直接删除 | 建议处理方式 |
|---|---|---|---|
| 完全重复 | 商品 ID、批次和字段全部相同 | 是 | 使用唯一键或幂等写入拦截 |
| 入口重复 | 搜索页、推荐位和店铺页指向同一商品 | 通常是 | 映射到同一个商品实体,保留来源入口 |
| 规格重复 | 同款商品的颜色、尺寸或容量不同 | 否 | 建立 SPU 与 SKU 的父子关系 |
| 店铺重复 | 不同销售主体销售相同或相似商品 | 通常否 | 保留店铺维度,另建同款关联 |
| 时间重复 | 同一商品在不同日期被再次采集 | 否 | 保存历史快照,更新当前状态 |
这五类记录在数据库里可能都表现为“多了一行”,但对选品分析的含义完全不同。完全重复会污染统计,入口重复需要归并,规格重复需要下沉到 SKU,店铺重复反映渠道竞争,时间重复则是趋势分析的基础。
我的判断是:去重规则必须写在数据模型之前被讨论,而不能等数据已经入库后再临时补一个去重脚本。如果商品实体、销售主体和历史状态没有分开,后续任何清洗动作都容易变成不可逆的数据损失。

很多选品报表只展示“商品数”,但开发人员最好同时提供三个口径:商品实体数、SKU 数和店铺商品数。商品实体数用于判断市场中有多少种产品,SKU 数用于观察规格和价格分布,店铺商品数用于衡量销售主体的竞争密度。
例如,一款保温杯有 12 种颜色和 3 种容量,可能对应 36 个 SKU,但在产品品类分析中通常应计为 1 个 SPU。如果把 36 个 SKU 都当成 36 个商品,某个品牌的商品丰富度就会被误判;如果反过来把所有 SKU 合并,又无法分析容量与价格的关系。
项目刚开始时,不建议一上来就做复杂的跨平台图片识别或语义匹配。投入产出比最高的顺序通常是:先拦截完全重复,再规范 URL,接着使用平台稳定商品 ID,最后才处理标题相似和跨平台同款。
原因很简单。完全重复和 URL 重复往往能解释大部分“记录虚高”,而跨平台同款识别需要更多字段、人工复核和回滚机制。如果平台内基础主键还没有稳定,直接做跨平台匹配,通常会把错误合并带入整个分析链路。
一个商品可能同时出现在关键词搜索结果、类目列表、店铺首页、相关推荐和活动页面。它们的 URL 可能不同,返回字段也可能不同,但最终指向同一个商品详情页。
如果系统把每个入口返回的记录直接写入商品表,某个被平台频繁推荐的商品就会被计数多次。此时,报表看似抓到了更多市场样本,实际测量的是“商品被不同入口展示了多少次”,而不是“市场上有多少个商品”。
这两个指标都可能有价值,但必须分开命名。前者可以用于研究曝光路径或流量入口,后者才适合用于商品数量、品牌覆盖率和竞争密度统计。
我在设计采集任务时,会特别检查分页边界,而不是只看第一页是否正常。某些接口的排序会实时变化,抓取第 1 页和第 2 页之间商品位置发生移动,就可能出现跨页重复或漏采。
另一个高频问题是失败重试。任务在写入数据库前超时,调度器认为整批失败并重新执行;实际上部分记录已经成功写入。若写入逻辑只是 INSERT,而没有唯一索引或幂等键,重试一次就可能制造一批重复数据。
“任务失败”不等于“没有任何数据写入”。开发流程必须把请求状态、解析状态、写入状态和业务批次状态分别记录,否则重跑行为无法预测。
选品人员常见的反馈是:“这个类目商品数怎么突然涨了 30%?”开发人员第一反应可能是接口返回变多了,但真正原因可能是分页逻辑修改、URL 参数变化或同一商品被多个入口重复计数。
因此,数据异常排查不能只看爬虫日志,还要对比去重前后数量、不同来源占比、唯一商品 ID 覆盖率和每日新增实体数。一个数据采集系统如果只能回答“抓了多少行”,却回答不了“新增了多少真实商品”,它还不具备支撑选品决策的条件。

在实际项目中,类似九数云这类数据分析与可视化工具适合把清洗后的商品、SKU、店铺和快照数据连接起来,制作去重前后对比、重复率趋势、价格带分布和类目筛选看板。它能让业务人员更快发现异常,也能减少反复导出表格的工作。
但工具本身不会自动知道“红色、黑色和蓝色是不是应该合并”,也不会天然判断两个不同平台的商品是否为同款。可视化工具解决的是发现问题和协作决策,主键设计、清洗规则和数据责任仍然属于开发流程。
如果使用九数云进行选品分析,我建议至少提供以下字段:平台、店铺、商品实体 ID、SKU ID、规范化 URL、原始 URL、商品标题、品牌、规格、价格、评论数、评分、采集时间、任务批次和数据质量状态。这样业务看到异常时,可以沿着看板回溯到具体商品和采集批次。
标题适合作为辅助匹配特征,不适合单独做唯一主键。标题可能被截断,也可能包含颜色、促销词、套装数量和物流信息。同一产品在不同页面标题略有变化,并不代表商品实体发生变化。
反过来,两个标题高度相似的商品也可能不是同一个产品。品牌不同、型号不同、包装数量不同,都会改变采购成本和竞争关系。仅凭文本相似度自动合并,容易出现“看起来更干净,业务上更错误”的结果。
更稳妥的做法是将标题用于候选召回,再结合品牌、型号、规格、店铺和平台 ID 进行确认。对于中等相似度的记录,进入待审核队列,而不是强制合并。
删除 utm、tracking、排序和分页参数,确实能消除一部分入口重复,但 URL 仍然可能因为地区、语言、子域名或登录状态产生变化。有的平台同一商品还可能拥有多个合法详情路径。
所以 URL 规范化应当作为匹配层,而不是唯一的业务身份层。平台提供稳定商品 ID 时,应优先使用平台 ID;没有稳定 ID 时,再将规范化 URL、品牌、型号和规格组合起来形成候选键。
标题和价格都可能变化。促销期间价格下降,标题增加“限时折扣”或“升级版”字样,如果把二者作为主键,同一商品会被误判为多个商品。更严重的是,价格变化本来就是选品研究需要观察的指标,不能因为它变动就生成新的商品实体。
正确的结构是:商品实体表保存相对稳定的身份信息,价格快照表保存某个时间点的价格。这样价格变化可以被记录,而不会制造新的商品。
一个商品拥有多个规格,可能意味着更强的供应链能力、更多的价格带覆盖或更复杂的库存风险。如果直接合并 SKU,运营人员看不到不同容量、颜色和套装的表现差异。
如果当前选品目标只关注“产品方向”,可以在 SPU 层汇总;如果目标是确定采购规格、定价或库存,则必须保留 SKU 层。去重的目标不是让表格看起来更短,而是让每一行都对应一个明确的分析对象。
选品不是只看当前排名。价格从 39 元降到 29 元、评论数从 800 增长到 1,200、评分从 4.6 变成 4.4,这些变化本身就是判断市场趋势的重要证据。
如果每天抓取后都覆盖昨天的数据,系统只能告诉你“现在是什么样”,无法回答“它是如何变成现在这样”。对于竞争度、评论增速和价格稳定性分析,历史快照通常比当前值更有价值。
人工表格适合做小规模核验,但不适合作为长期去重机制。每次导出后由运营人员删除重复行,既无法保证不同人员标准一致,也无法将处理结果回写到原始数据链路。
更合理的方式是把人工判断沉淀为规则:哪些字段参与匹配、哪些情况必须保留、哪些记录进入复核、合并后保留哪条主记录。人工应该处理边界案例,而不是每天重复处理同一种机械重复。

我通常会要求项目先回答四个问题:什么是商品?什么是规格?什么是销售主体?什么是一次观察?如果这四个问题没有答案,开发人员很难知道一条新记录应该更新旧记录、创建 SKU,还是保存为历史快照。
| 对象 | 建议定义 | 适合保存的字段 | 典型用途 |
|---|---|---|---|
| 商品实体 | 可被消费者视为同一产品方向的对象 | 品牌、型号、类目、基础标题 | 市场规模、品类分析 |
| SKU | 具有具体规格并可独立交易的对象 | 颜色、尺寸、容量、包装数量 | 价格、库存、规格偏好 |
| 店铺商品 | 某店铺经营的某个商品或 SKU | 店铺 ID、商品 ID、店铺价格 | 店铺竞争、渠道比较 |
| 商品快照 | 某商品在某次采集时的状态 | 价格、评分、评论、排名、库存状态 | 趋势、变化率、历史回溯 |
| 采集任务 | 产生数据的执行单元 | 任务 ID、来源、开始时间、状态 | 重试、审计、异常排查 |
商品实体的唯一键通常不应包含价格和采集时间,因为这两个字段会变化。SKU 的唯一键则需要包含规格信息,店铺商品键还应加入店铺维度,历史快照键则需要加入采集时间或版本号。
一个常见的设计思路如下:
这些键并不是所有平台都能直接获得。若平台没有 SKU ID,需要根据规格组合生成稳定键;若连稳定商品 ID 都没有,则要把匹配结果标记为“确定、疑似和待复核”三种状态,而不是假装所有记录都能自动识别。
这是我认为最重要的流程优化之一。很多系统只有“合并”和“不合并”两个结果,导致开发人员不得不提高或降低一个阈值来覆盖所有情况。实际项目更适合使用三段式判断。
平台商品 ID、店铺商品 ID 或可靠的业务编码一致时,可直接归并到同一实体。写入时使用唯一约束,重复请求只更新采集状态或快照,不新增商品实体。
品牌、型号和规格高度相似,但缺少稳定 ID 时,记录为候选匹配。系统可以计算相似度并进入复核列表,但不应直接影响核心选品统计,直到匹配状态被确认。
品牌、型号、规格和类目存在明显差异时,保留独立实体。即便标题很相似,也不能为了降低重复率而强行合并。
数据治理最怕不可解释。两条记录被合并后,系统至少应记录合并时间、操作方式、匹配字段、匹配分数、规则版本和原始记录 ID。这样业务人员发现商品数量变化时,可以追查是平台数据变了,还是匹配规则升级了。
合并关系最好支持撤销,而不是物理删除原记录。对于跨平台同款识别尤其如此,因为图片相似、标题相似并不必然代表供应链和销售关系相同。

原始层的作用不是直接给业务看,而是保留事实证据。建议保存原始 URL、来源页面、采集时间、响应状态、原始标题、平台返回的 ID、任务批次和解析版本。
有了原始层,后续可以在规则变化后重新清洗。例如,第一次把“500ml”解析成文本,第二次希望拆成容量数值和单位,如果原始字段已被覆盖,就只能重新请求平台,既增加成本,也可能因为页面变化而无法复原。
URL 标准化通常包括协议统一、域名大小写处理、默认端口删除、尾部斜杠处理、追踪参数剔除、参数排序和锚点删除。但不同平台的参数含义不同,不能使用一份全局黑名单覆盖所有站点。
尤其要注意,有些参数虽然看起来像追踪参数,实际承载地区、语言、变体或页面上下文。删除前应验证:去掉该参数后是否仍然指向同一个商品,页面内容是否发生实质变化。
原始 URL:
https://shop.example.com/item/ABC123?color=red&utm_source=search&page=2
规范化入口 URL:
https://shop.example.com/item/ABC123?color=red
商品实体键:
example.com + ABC123
SKU 业务键:
example.com + ABC123 + color=red
上面的示例说明,URL 可以有多个用途:规范化入口 URL 负责识别页面,商品实体键负责识别产品,SKU 业务键负责识别具体规格。把它们压缩成一个字段,后续很难兼顾入口去重和规格保留。
标题清洗不是把所有标点删除就结束了。品牌、型号、容量、包装数量和颜色等字段,应根据后续分析单独拆分。价格也不能只保存一个字符串,而应至少拆成数值、币种、促销状态和价格类型。
幂等写入的目标是:同一批数据重复执行一次或多次,最终结果不发生错误叠加。它不能只依赖代码里的“先查询再插入”,因为并发任务下两个进程可能同时查询到“没有记录”,然后同时插入。
更稳妥的组合是:数据库唯一索引负责最终兜底,业务层使用 upsert 或冲突更新,任务层记录批次状态,异常记录进入单独队列。这样即使任务重试,系统也不会因为重复请求制造多个商品实体。
CREATE UNIQUE INDEX uq_product_entity ON product_entity(platform_code, platform_product_id); CREATE UNIQUE INDEX uq_sku_entity ON product_sku(platform_code, shop_id, platform_product_id, sku_key); CREATE UNIQUE INDEX uq_snapshot ON product_snapshot(product_key, snapshot_date);
示例中的索引只是通用设计示意,实际字段需要根据平台标识稳定性、数据更新频率和数据库类型进行调整。索引越多并不一定越好,写入量很大时还要评估索引维护成本。
建议给记录增加质量状态,例如“有效”“缺关键 ID”“疑似重复”“待复核”“解析异常”“来源失效”。不要把所有异常数据直接删除,因为异常本身可以帮助定位平台页面变化和解析器问题。
业务分析时只读取符合统计条件的记录,开发排查时则可以查看完整记录。这样既不会让异常数据污染选品看板,也不会让开发人员失去故障现场。

下面使用一组情景案例说明流程,不代表某个真实平台的公开统计。假设团队要研究一个小家电类目,采集了搜索结果、类目页面和 80 家店铺的商品列表,原始数据共 10,000 条。
| 来源 | 原始记录 | 识别出的商品实体 | 主要重复原因 |
|---|---|---|---|
| 关键词搜索页 | 5,000 条 | 4,100 个 | 分页边界、排序变化、推荐混入 |
| 类目页面 | 3,000 条 | 2,300 个 | 与搜索页共享热门商品 |
| 店铺商品列表 | 2,000 条 | 1,700 个 | 跨店铺同款和同店多规格 |
| 合计 | 10,000 条 | 7,400 个 | 多入口和规格层级混合 |
如果直接用 10,000 条记录计算商品数量,市场规模会被高估约 35.1%。这个比例只是情景计算,公式是(10,000-7,400)÷10,000,并不代表所有平台都会出现相同水平的重复。
更重要的是,2,600 条差异记录不能全部当成垃圾。经过复核,其中一部分是同一商品从不同入口出现,另一部分是不同店铺销售的同款,还有一部分是不同颜色和容量的 SKU。真正应从商品实体统计中剔除的,是重复入口和完全重复;店铺关系和 SKU 关系需要被保留。
假设原始数据中某品牌有 1,200 条记录,去重后只有 620 个商品实体,其中 420 条来自搜索页,390 条来自类目页,390 条来自店铺页。若不去重,品牌会被误判为拥有更高的商品覆盖和更强的市场占有。
类似偏差也会出现在评分和评论统计中。热门商品因为同时出现在多个入口,评论数可能被重复纳入均值;而长尾商品只出现一次,权重就会被不公平地稀释。
因此,选品看板至少应区分“去重商品数”“商品入口次数”“店铺覆盖数”和“SKU 数”。这四个指标分别回答市场有多大、平台推荐多强、销售主体多少和规格复杂度多高,不能合并成一个模糊的商品数量。

如果团队使用九数云制作选品分析看板,可以设置三个互相联动的页面。第一个页面展示采集概况,包括来源、批次、原始记录数、解析成功率和重复率;第二个页面展示商品、SKU、店铺三个层级的数量;第三个页面展示价格、评分、评论增速和类目竞争情况。
看板中最好加入“查看原始记录”或“查看来源入口”的下钻路径。例如,业务发现某个类目的商品数突然上升,可以从类目汇总下钻到商品实体,再下钻到原始 URL 和采集批次,判断增长来自真实新增还是入口重复。
这类工具的价值在于降低跨角色沟通成本。开发人员不必每次手工导出异常样本,运营人员也不必只凭截图反馈问题。但最终指标口径仍需写在数据字典中,包括去重条件、统计日期、异常记录是否剔除和历史快照是否参与计算。
这是最容易治理的情况。将平台代码、店铺 ID 和商品 ID 组合成实体键,使用数据库唯一约束防止重复写入。对于不同规格,如果平台同时提供 SKU ID,则将 SKU ID 作为子层主键。
这种方案的优点是自动化程度高、误合并风险低,适合大批量日常增量抓取。需要注意的是,平台 ID 只在平台内部有意义,不能直接拿来做跨平台统一商品 ID。
可以先建立页面实体键,将域名、路径和经过验证的关键参数组合起来。之后再用品牌、型号、规格和店铺信息补充匹配,逐步形成内部商品实体。
此时建议采用“确定匹配和候选匹配并存”的设计。页面键完全一致时可以自动归并;字段高度相似但 URL 不同的记录进入候选表,等待规则确认或人工复核。
不要为了追求自动化,把相似度阈值设置得过低。一个错误合并会让后续价格、评价和销量被聚合到错误商品上,修复成本通常高于暂时保留两条记录。
跨平台去重的目标往往不是“删除重复商品”,而是建立同款关联。因为同一个产品在不同平台的店铺、价格、库存和评价都具有比较价值,直接合并成一条记录会丢失渠道信息。
建议建立“平台商品,统一产品”的映射表。平台商品仍然保留原平台 ID和店铺关系,统一产品作为关联层,记录品牌、型号、规格、编码和匹配置信度。
| 匹配等级 | 判断依据 | 自动处理 | 业务用途 |
|---|---|---|---|
| 高置信度 | 条码或型号完全一致,规格一致 | 自动关联 | 跨平台价格和供应渠道比较 |
| 中置信度 | 品牌、型号和图片高度相似 | 进入人工复核 | 候选同款池,不直接影响核心统计 |
| 低置信度 | 仅标题相似或类目相同 | 不自动关联 | 保留为独立商品 |
如果每天只有几百或几千条记录,不必一开始就搭建复杂的数据湖。可以先使用关系型数据库、规范化字段、唯一索引和一张异常复核表,把最重要的规则跑通。
小规模项目最容易犯的错误是“先人工清理,等数据量大了再治理”。一旦人工表格积累了数十万条记录,历史合并关系和原始来源很难恢复。即使规模小,也应保留原始 URL、采集时间、来源和处理状态。
需要将采集、解析、标准化、实体匹配和入库解耦。采集任务只负责获取原始数据,解析服务负责抽取字段,匹配服务负责实体识别,写入服务负责幂等落库。
同时设置重复率、关键 ID 缺失率、解析成功率、单批次新增实体数和异常重试次数等监控指标。任何指标突然变化,都应触发告警或暂停进入核心报表。

一个稳定的抓取流程,至少应拆成采集、解析、标准化、实体匹配、入库和指标计算六个阶段。每个阶段都应有输入、输出、状态和失败原因,不能把所有逻辑塞进一个长脚本。
阶段拆分的直接价值是避免整批重跑。假设 10,000 条原始记录已经完成采集,但只有匹配服务失败,系统应从匹配阶段恢复,而不是重新请求全部页面。
任务批次是排查重复的基本线索。建议记录任务名称、来源平台、查询词或类目、开始和结束时间、代码版本、规则版本、成功数量、失败数量和写入数量。
规则版本尤其重要。今天使用平台 ID匹配,明天增加型号相似度匹配后,去重结果可能发生变化。如果没有规则版本,业务会误以为市场商品数量真实变化,实际上只是清洗逻辑发生了变化。
纯全量抓取容易产生大量重复处理,纯增量抓取又可能因漏采和状态失效而逐渐偏离真实情况。更稳妥的方式是日常增量加周期性全量校准。
重复率可以作为健康度指标,但它不能单独说明流程好坏。重复率突然下降,可能是去重规则生效,也可能是商品 ID解析失败后所有记录被判定为不同;重复率突然升高,可能是入口增加,也可能是分页逻辑出错。
我建议至少同时观察五个指标:重复率、平台 ID覆盖率、关键字段缺失率、单批次新增实体率和任务重试率。只有这些指标结合起来,才能区分市场变化、平台变化和程序故障。

开发数据库中的所有记录不应直接暴露给选品人员。建议建立可用数据层,明确哪些状态允许进入商品数量、价格带和竞争度统计,哪些状态只能用于异常监控。
例如,确定有效记录可以进入核心分析;候选匹配记录可以在“待确认商品”页面展示;解析异常记录只进入质量看板;历史快照进入趋势模型,但不计入当前商品数量。
这种分层可以避免业务人员在同一张表里自行筛选,减少不同人员使用不同过滤条件造成的结论冲突。
按平台商品 ID去重,速度快、解释性强,适合平台内实体识别。按标题、品牌和规格做相似匹配,覆盖面更广,但计算成本和误合并风险都会增加。跨平台图片、文本和编码综合匹配,准确性可能更高,却需要更多字段和复核资源。
| 方案 | 开发成本 | 处理速度 | 误合并风险 | 适合场景 |
|---|---|---|---|---|
| 平台 ID 去重 | 低 | 快 | 低 | 平台内、标识稳定的商品采集 |
| URL 规范化去重 | 中 | 较快 | 中 | 多入口页面归并 |
| 多字段规则匹配 | 中高 | 中等 | 中 | 缺少稳定 ID 的平台内匹配 |
| 模型相似度匹配 | 高 | 较慢 | 取决于训练和阈值 | 跨平台同款候选识别 |
| 模型加人工复核 | 最高 | 较慢 | 最低 | 高价值品类和关键决策样本 |
不是所有数据都值得同样的治理成本。若某个类目只是用于趋势观察,可以接受一部分候选记录暂不合并;若数据将用于采购决策、供应商谈判或大规模备货,错误合并的成本就会明显上升。
可以按商品价值、流量、订单贡献、采购金额或分析影响范围设置复核优先级。热门商品和高金额商品优先复核,长尾低影响商品采用自动规则,能在准确性和成本之间取得更现实的平衡。
当前报表追求及时,通常只需要商品最新状态;历史研究追求可比性,需要固定时间点的快照。若两者共用一张不断更新的表,任何一次回填或字段修正都可能改变过去的统计结果。
建议至少分为当前实体表、当前 SKU 状态表、历史快照表和质量异常表。数据量较大时,再根据查询性能将快照按日期或平台分区。
相似度模型并不是去重系统的起点。没有稳定的原始字段、错误样本和人工标注,模型输出很难验证。建议先积累一批已确认的重复与非重复样本,再评估是否值得引入模型。
即使使用模型,也应保留匹配依据和置信度。模型可以负责召回候选记录,最终是否合并仍需要业务可解释性,尤其是在涉及价格、销量和市场规模的核心指标时。


把商品、SKU、店铺、页面入口、历史快照和采集任务画成关系图。先明确哪些对象是一对多,哪些对象可以合并,哪些对象必须保留。这个动作看似简单,却能提前暴露大部分“商品数到底怎么算”的争议。
不要直接从百万级数据开始。选择一个类目、三个入口和若干店铺,抽取 1,000 至 10,000 条样本,人工标注完全重复、同商品多入口、同 SPU 多 SKU、跨店铺同款和独立商品。
这批样本的价值不是得到最终重复率,而是找出平台实际字段规律。开发人员应重点观察哪些 ID稳定、哪些参数影响页面、哪些规格字段经常缺失。
先实现平台 ID、店铺 ID、规范化 URL和任务批次的组合规则,建立唯一索引和 upsert。不要急于做复杂语义匹配,先确保重复任务不会产生重复实体。
把缺少 ID、字段冲突、标题相似但规格不同和跨平台疑似同款的记录单独存放。为每条记录保存匹配依据、规则版本和处理状态,让人工复核有明确的上下文。
至少计算商品实体数、SKU 数、店铺商品数、平均评分、价格中位数、评论增速和重复率。比较结果时不要只看商品数量下降了多少,还要看价格分布和竞争排序是否发生合理变化。
可以将已确认的数据接入九数云或其他分析工具,制作采集质量、实体层级、异常记录和选品指标四类视图。看板要支持按平台、类目、店铺、批次和商品实体下钻。
根据商品变化频率、平台访问限制和业务更新要求,决定哪些字段日常增量、哪些字段周期校准、哪些类目需要全量重抓。将规则写成文档,并把质量阈值配置成告警,而不是依赖某个开发人员记忆。
电商数据抓取的难点,从来不只是把页面内容搬到数据库,而是让数据库中的每一行都能被解释。它究竟代表一个商品、一个 SKU、一个店铺关系,还是某个时间点的状态?如果这个问题没有答案,再精美的报表也可能建立在重复计数之上。
我在流程设计中最看重的不是“去重率达到多少”,而是三个更实际的结果:同一任务重复执行不会制造新商品;业务人员能追溯每个商品来自哪里;历史数据不会因为今天的更新而失去过去的变化。
下一步不要先追求复杂算法,先选一个真实类目,建立商品实体、SKU、店铺和快照四层模型,抽取一批样本验证主键,再把确定性去重、异常复核和增量更新接起来。当数据流程能够解释“为什么合并、为什么保留、为什么新增”,选品研究才真正从数据展示进入可靠决策。
同时,涉及数据抓取时,应遵守目标平台的服务条款、访问频率限制和接口权限要求,只采集业务必要字段,避免处理不必要的个人信息。合规边界不是流程末端的附加说明,而应与数据源选择、字段设计和任务调度一起纳入系统方案。
我在做选品数据抓取时发现,同一个商品经常会从搜索页、分类页、推荐页和店铺页分别进入数据库。更麻烦的是,这些记录的 URL 可能不同,标题也可能有轻微变化,我不知道应该按什么标准判断它们是不是同一个商品。
重复数据通常不是单一的爬虫故障,而是“采集入口”和“业务对象”没有区分。一个商品可能同时出现在搜索结果、分类列表、相关推荐和店铺页面中;如果程序把每个页面地址都当成独立商品,重复记录就会迅速增加。
我排查过一批示例数据:原始抓取记录为 10,000 条,按平台商品 ID 去重后只剩 7,860 个商品实体。剩余记录并非全部应该删除,其中约 1,120 条属于不同 SKU,约 640 条属于不同店铺或历史快照,真正可以合并的页面重复记录约为 380 条。
重复类型常见原因处理方式 页面重复参数、分页、多个入口URL 规范化后合并 SKU 差异颜色、尺寸、容量不同保留 SKU,关联同一 SPU 历史快照价格、评论数随时间变化保留时间记录,不覆盖 店铺差异同款商品由不同商家销售保留店铺维度 因此,正确做法不是先写一个“删除重复行”的脚本,而是先定义商品、SKU、店铺、页面和时间快照五个层级。
没有这一步,去重规则越激进,误删真实业务数据的风险越高。
我曾经尝试过用标题清洗加相似度匹配来合并商品,结果把同一系列的不同容量误合并了。后来改用平台商品 ID,平台内的数据稳定很多,但跨平台抓取时又没有统一 ID,这种情况下到底应该怎样设计主键?
在平台内去重时,我的判断顺序是“稳定商品 ID优先,规范化 URL其次,标题和属性只做辅助”。商品标题适合帮助发现疑似同款,却不适合作为唯一主键,因为促销词、颜色、规格和语言差异都会改变标题。实际开发中可以把主键拆成多个层级,而不是强行使用一个全局键。
平台商品 ID解决平台内识别问题,店铺商品 ID解决同一平台多店铺问题,SPU 和 SKU 则解决商品系列与具体规格之间的关系。
匹配依据适用范围风险判断 平台商品 ID同一平台内通常最可靠,但要验证稳定性 店铺 ID+商品 ID多店铺数据避免不同店铺误合并 规范化 URL缺少业务 ID时需要剔除追踪和排序参数 品牌+型号+规格跨平台匹配依赖字段完整度 标题相似度疑似同款召回不建议直接自动合并 跨平台匹配时,我更建议采用置信度分层:品牌、型号、条码和规格完全一致时自动关联;
只有标题和图片相似时进入人工复核;证据不足则保留独立商品。自动合并必须记录匹配依据,否则后续发现误合并时很难撤销。
我的抓取任务每天定时运行,遇到接口超时就会重跑整批任务。几周后数据库里出现了大量相同商品,开发人员虽然加了一个去重 SQL,但任务执行时间和数据库体积仍然不断增加,我想知道问题到底出在采集还是入库。
这类问题通常同时出在两个环节:采集端重复获取,入库端又没有保证幂等。仅靠事后执行去重 SQL,只能清理结果,不能阻止任务重复消费、并发写入和失败重试带来的新重复。一个更稳妥的流程是:先保存任务批次和游标,再按商品唯一键执行 upsert;同一批次重复运行时,已有记录更新而不是再次插入。
数据库层还应设置唯一索引,让程序逻辑失误时由底层约束拦截重复写入。建议把商品当前状态与历史变化拆开。商品主表保存名称、品牌和平台 ID,状态表保存当前价格和库存,快照表保存某个采集时间点的价格、评分和评论数。这样既能避免当前数据重复,也不会因为去重而丢失价格变化。
策略解决的问题实施建议 增量抓取减少无变化商品重复请求按更新时间、游标或变更标记抓取 唯一索引阻止重复入库按平台、店铺、商品 ID设计 幂等批次避免失败重跑产生副本记录任务 ID和数据版本 定期全量校准发现增量遗漏按日常增量、周期全量组合 我的经验是,增量抓取并不等于永远不做全量抓取。
更合理的方式是日常使用增量降低成本,每周或每月进行全量校准,并监控“新增记录数、更新记录数、重复拦截数和异常率”四个指标。
以前我只关注抓取总量,认为采集到的商品越多,选品分析越全面。后来发现同一商品从多个入口重复出现后,某些品类的商品数量、评论总量和价格分布都被放大,导致排名靠前的品类并不一定是真正有机会的品类。
重复数据对选品最危险的影响,不是浪费存储空间,而是让错误结果看起来很有说服力。商品数量被重复计算后,竞争度会被高估;评论和销量被重复聚合后,热门程度又可能被夸大,两个方向会同时误导决策。下面是一个简化示例。某品类原始记录为 1,200 条,去重后只有 900 个商品实体;
如果直接计算商品数量,竞争规模会被高估约 33%。同样,若同一商品的评论数在三个入口重复出现,评论总量可能被错误放大到原来的三倍。
分析指标未去重的典型偏差建议统计口径 商品数量多入口重复导致市场规模虚高按商品实体或 SPU 统计 SKU数量规格被误当成独立商品商品和 SKU 分开统计 平均评分高频重复商品权重过高先按商品去重再计算 价格区间重复记录改变分布权重明确当前价与历史价 竞争度重复商品被误判为不同竞争者按商品、店铺分别建口径 我建议选品报表至少同时展示“原始记录数、去重商品数、SKU数、店铺数和疑似重复数”。
如果报表只给出一个商品总量,运营人员很难判断数据规模是真实市场规模,还是抓取入口数量的反映。最后还要统一指标口径。例如销量是实际订单量、页面估算值还是区间值,评论数是当前值还是历史累计值。去重只能解决对象重复,不能替代指标定义;主键正确但统计口径错误,选品结论仍然不可靠。


读者评论
文章把重复数据区分为完全重复、入口重复、规格重复和历史快照,层次比较清楚。尤其是强调不能把所有多行记录都直接删除,这对选品分析很有参考价值。
分页变化和失败重试确实容易造成重复写入。文中提到用唯一键和幂等机制拦截,属于比较基础但经常被忽略的工程问题,建议再结合具体数据库方案说明。
SPU、SKU、店铺商品数分开统计的思路很实用。不同分析目标使用不同粒度,能避免把规格数量误当成商品数量,不过实际落地时需要提前统一业务口径。
不建议只用标题或价格去重这一点比较客观。标题、价格都会变化,平台商品ID和规范化URL也并非始终可靠,采用多字段匹配并保留人工审核更稳妥。
文章使用的重复率和采集量数据属于情景模拟,不能直接代表所有平台,但用于说明原始记录增长不等于真实商品增长还是很直观的。