文章表 12 万行里标题重复的有 4.1 万条,最多的一篇出现 3 次,三次的 url 分别带 utm_source=a、utm_source=b 和完全不带参数。乍看像缓存或者权限的锅,追下去往往不是。

from urllib.parse import urlsplit, parse_qsl, urlencode
u = urlsplit(raw)
q = [(k, v) for k, v in parse_qsl(u.query) if not k.startswith('utm_')]
key = u._replace(query=urlencode(sorted(q)), fragment='').geturl()

追下去是这么回事:去重键取的是完整 URL,查询参数不同就被当成新页面。站内推荐位和分页链接会自动加跟踪参数,同一篇文章因此有多个地址。

「抓取数据去重」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

偶发问题先统计频率,一小时几次和一天一次,查法完全不同。改完顺手把文档补一句,省得下次自己重新推一遍。

监控和日志的时间要对上,时区不一致会多绕很大一圈。

具体做法是,入库前先归一化 URL 去掉 utm 和 fragment;查询参数排序后再拼;按归一化结果算 hash;数据库加唯一索引兜底。

验收就看一点,归一化后重跑同一批任务新增 0 条重复,表里总数从 12 万降到 8.6 万。

作者 9823189