本文目录导读:

解析地址信息是一个常见的需求,通常指从一段非结构化文本(如“北京市海淀区中关村大街1号”)中提取出省、市、区、街道、门牌号等结构化字段。
根据不同场景和精度要求,有几种主流的解析方法,以下是详细的脚本方案:
使用现成的开源库(推荐,最省力)
这是最推荐的方式,无需自己处理复杂的规则和机器学习模型。
Python - addrParse / postaddr
这两个库专门用于中国地址解析,基于规则和词典。
# 安装: pip install addrparse
from addrparse import parse_addr
# 或者使用 postaddr
# pip install postaddr
# from postaddr import parse
address = "广东省深圳市南山区科技园南区粤海街道R2-B栋5楼"
result = parse_addr(address)
print(result)
# 输出示例: {'province': '广东省', 'city': '深圳市', 'district': '南山区', 'street': '粤海街道', 'detail': 'R2-B栋5楼'}
Python - 高德/百度地图 API(最准确,但需联网)
适合需要极高准确率(如电商、物流)且允许网络请求的场景。
import requests
# 以高德地图地理编码API为例(需申请Key)
API_KEY = "你的高德Key"
address = "北京市朝阳区望京SOHO T1"
url = f"https://restapi.amap.com/v3/geocode/geo?key={API_KEY}&address={address}"
response = requests.get(url)
data = response.json()
if data['status'] == '1' and data['geocodes']:
# 解析结构化地址
addr_component = data['geocodes'][0]
print(addr_component['province']) # 北京
print(addr_component['city']) # 北京市
print(addr_component['district']) # 朝阳区
print(addr_component['street']) # 望京街道
基于规则的通用脚本(轻量级,无依赖)
如果你不想调用API也不想下载第三方库,可以用正则表达式加词典实现基础解析。
Python 示例(纯规则+省市区词典)
import re
# 定义省市区简单词典(实际使用时需要更全的列表)
PROVINCES = ["北京", "天津", "上海", "重庆", "河北", "山西", "广东", "深圳", "浙江"...]
CITY_KEYWORDS = ["市"]
DISTRICT_KEYWORDS = ["区", "县", "县级市"]
STREET_KEYWORDS = ["街道", "镇", "乡", "路", "街", "大道"]
def parse_address(address):
result = {
"province": "",
"city": "",
"district": "",
"street": "",
"detail": ""
}
# 1. 提取省份(简单匹配)
for prov in PROVINCES:
if address.startswith(prov):
result["province"] = prov
address = address[len(prov):]
break
# 2. 提取城市(匹配第一个出现的“市”)
city_match = re.search(r"(.*?市)", address)
if city_match:
result["city"] = city_match.group(1)
address = address[city_match.end():]
# 3. 提取区/县
district_match = re.search(r"(.*?[区县])", address)
if district_match:
result["district"] = district_match.group(1)
address = address[district_match.end():]
# 4. 提取街道(匹配第一个出现的街道/镇/路等)
street_match = re.search(r"(.*?[街道镇路大道])", address)
if street_match:
result["street"] = street_match.group(1)
address = address[street_match.end():]
# 5. 剩余部分为详细地址
result["detail"] = address.strip()
return result
# 测试
addr = "广东省深圳市南山区粤海街道科技园南路1号"
print(parse_address(addr))
# 输出:{'province': '广东', 'city': '深圳市', 'district': '南山区', 'street': '粤海街道', 'detail': '科技园南路1号'}
使用 NLP 模型(适合复杂、不规则文本)
对于用户手写输入、包含错别字或非常规格式的地址,可以使用基于BERT的命名实体识别(NER)模型。
示例:使用 pip 安装 transformers 加载预训练模型
# 安装: pip install transformers torch
from transformers import pipeline
# 加载中文地址解析模型(如清华大学的地址解析模型)
# 注意:可能需要从 HuggingFace 下载特定模型
ner_pipeline = pipeline("ner", model="bert-base-chinese") # 通用NER
# 更推荐使用专门训练的地址模型(如 "Address-NER")
# 这里以简单示例说明:
address = "上海市浦东新区张江高科技园区郭守敬路498号"
result = ner_pipeline(address)
# 输出结果需要结合规则后处理成省市区格式
print(result)
# 实际生产环境可使用:https://huggingface.co/uer/bert-base-chinese-ner
常见问题与优化技巧
- 处理缺失字段:很多地址会省略省份或城市,北京市朝阳区”北京”既是省也是市,建议建立层级映射词典:
直辖市映射:北京 -> 省:北京,市:北京县级市映射:如果提取到“昆山市”,应识别为城市,并映射到江苏省。
- 处理前缀:用户可能输入“收货地址:”、“我家在”等前缀,需先用正则过滤:
address = re.sub(r'^(收货地址|地址|我家在|送至)[:: ]', '', raw_text)
- 处理模糊匹配:用户可能写“南京鼓楼区”而非“南京市鼓楼区”,规则需要允许“市”字可省略。
- 性能优化:如果处理大量数据(百万级),
addrParse库比调用API快数百倍。
如何选择?
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 小批量、高精度 | 高德/百度地图 API | 正确率接近100%,自动修正错别字 |
| 通用开发、个人项目 | addrParse / postaddr 库 |
无网络请求,本地快速解析 |
| 批量清洗历史数据 | 基于规则的纯脚本(方案二) | 速度快,可定制性强,无外部依赖 |
| 用户手工输入、口语化严重 | NLP模型(BERT) | 对不规则文本(如“张江镇上”)理解能力强 |
给新手的建议:先试 pip install addrparse,调用一次函数看结果,如果效果满意,就无需折腾其他方案。