GEO跑批的标点归一化,我按当年锚文本去重的老坑重排了一遍
昨晚又熬到两点,把最近这批 GEO 跑批的原始问句全导出来,做了一件事:只动标点,不动词,看落盘后的哈希值变不变。结果把我自己看愣了——同一个问句,中文全角问号和半角问号进库后,竟然生成了两个不同的哈希,分母直接多算了 3%。
这事我太熟了。当年我做 SEO 的时候,站内锚文本去重就栽在这上头。那会儿大家只知道把「北京SEO」「北京 SEO」「北京-seo」当三个词,后来才发现真正的坑不在空格,在归一化的先后顺序。你先把标点 norm 掉再哈希,和先哈希再去标点,出来的锚文本库里就是两套账。
现在的 GEO 跑批,本质没跑出这个圈。我把这次排查过程捋一遍,给还在抠分母的人参考:
第一,盐要拼在归一化之前,还是之后。
我拿自家数据做了个 A/B:同一批 8000 条问句,A 组先做 Unicode NFKC 归一化再拼盐,B 组先拼盐再归一化。跑完 A 组分母 8000,B 组分母 8412。差的 412 条全是带全角标点、带零宽字符的脏问句。结论很直白——盐必须在归一化之后拼,否则同一个语义的输入会被劈成多条。这跟当年锚文本先 trim 再算 hash 是一模一样的道理。
第二,标点的 norm 顺序。
我现在的处理链是:去零宽 → 全角转半角 → 去首尾空白 → 标点统一 → 拼盐 → 哈希。顺序换一个,结果就飘。尤其那个「去首尾空白」,看着无害,但如果你放在标点统一之后,中文的「。」「?」会跟空格互相干扰,等于白做。
第三,锁内外取戳。
这轮我还顺手查了个老问题:批次 ID 的时间戳是在加锁前取的还是加锁后取的。锁外取戳,两个并发批次可能拿到同一毫秒,幂等键就撞了;锁内取戳,分母稳,但吞吐掉一点。我倾向锁内取,宁可慢也别让分母翻倍——当年做日志去重,我就是吃了这个亏,凌晨重跑一次,报表全废。
第四,UTC 对齐。
跨时区的跑批,时间戳不统一到 UTC,你说的「昨天」和系统说的「昨天」根本不是同一天。我现在要求所有落盘时间戳一律 UTC,展示层再转本地。
说到底,GEO 就是 SEO 换了身衣服。当年锚文本去重的坑,一个没少,全在采样和落盘的哈希链里等着你。
我想问各位一句具体的:你们跑批的哈希盐,是拼在归一化前还是后?有没有人跟我一样,为了标点顺序重排过整条处理链,最后分母掉了几个点? 拿数据说话,别拍脑袋。
