构建数据库入库前数据去重管道:乱序地址条目识别方案咨询
这是个非常典型的地址去重场景,我之前做本地商户数据同步的时候也遇到过几乎一模一样的问题,分享一套可以落地的处理管道方案给你:
整个管道分为三个核心阶段,一步步把“看起来不一样但实际相同”的地址统一成标准格式,再通过校验避免重复入库。
1. 地址标准化:把异构地址转成统一格式
这一步是去重的关键,目的是让所有语义相同的地址变成完全一致的字符串。具体可以拆成几个小步骤:
统一字符大小写:把所有字母转成小写(或者全大写,保持一致就行),消除大小写差异。比如用Python代码实现的话:
normalized_address = raw_address.strip().lower()你的例子里“364 debs lane”和“364 Debs Lane”经过这一步就会变成一样的。
拆分并提取地址组件:把地址拆分成「门牌号」和「街道内容」两部分(如果是更复杂的地址,还可以拆城市、邮编,但你的场景里主要是门牌号和街道)。可以用正则表达式快速提取数字部分:
import re # 提取开头的数字门牌号 match = re.match(r'^(\d+)\s+(.*)', normalized_address) if match: house_number = match.group(1) street_part = match.group(2)这样“364 Lane Debs”会拆成
house_number="364",street_part="lane debs"。标准化街道内容的顺序:把街道部分的单词按固定规则排序(比如字母顺序),或者按照「街道名称+街道类型」的逻辑重组。比如把
street_part按空格分割成单词,排序后再拼接:sorted_street = ' '.join(sorted(street_part.split()))这样“lane debs”会变成“debs lane”,和“Debs Lane”标准化后的结果完全一致。
(可选)标准化街道类型缩写:如果遇到“Ln”“St”这类缩写,可以提前做一个映射表转成全称,比如
{"ln": "lane", "st": "street"},替换掉缩写,进一步消除格式差异。
经过这几步,你的四个地址会变成:
- 364 Lane Debs →
364 debs lane - 364 Debs Lane →
364 debs lane - 365 Lane Debs →
365 debs lane - 364 debs lane →
364 debs lane
2. 生成唯一标识(哈希值)
把标准化后的地址字符串生成一个哈希值(比如MD5、SHA256),这个哈希值可以作为判断重复的唯一键。比如Python代码:
import hashlib def generate_address_hash(standardized_addr): return hashlib.sha256(standardized_addr.encode('utf-8')).hexdigest()
这样语义相同的地址会生成完全一样的哈希值,不同的地址(比如门牌号不同的365那条)哈希值完全不同。
3. 入库前的重复校验
在把数据存入数据库前,先做两步校验:
- 内存/缓存层面校验:如果是批量处理,可以把已经处理过的哈希值存在一个集合里,每处理一条先查集合,存在就跳过。
- 数据库层面校验:在数据库里给哈希值字段加唯一约束,同时入库前先执行
SELECT查询,检查是否存在相同的哈希值。双重保障避免漏网之鱼。
- 如果是处理国际地址,或者包含公寓号、邮编的复杂地址,建议用专门的地址解析库(比如Python的
usaddress针对美国地址,pgeocode支持多国地址解析),能更精准地拆分组件。 - 门牌号如果包含字母后缀(比如364A、364-B),要完整保留,不能只提取数字,否则会把364和364A误判成同一个地址。
内容的提问来源于stack exchange,提问作者Kalpesh Kadam

