Python地址标准化处理 | 批量解析经纬度

运行环境:Jupyter notebook(python 3.12.7)

维度

chinese-address-parser

高德API

准确性

中(依赖规则)

高(基于海量数据+AI模型)

功能范围

仅地址结构解析

地址解析、地理编码、逆地理编码、POI搜索等

复杂地址处理

弱(无法处理模糊输入)

强(支持语义分析、别名匹配)

经纬度获取

不支持

支持(地理编码接口返回经纬度)

网络依赖

无需网络

必须联网

成本

免费

免费额度有限,超量需付费(0.3元/次)

适用场景

离线、小批量标准化地址

在线、高精度、复杂场景

chinese-address-parser不支持直接获取经纬度,
因此为了解析出标准地址和经度纬度,这里主要使用的是高德API。


方法与步骤

(1)准备地图API KEY

申请高德地图KEY + 百度地图AK(免费版一般够用)→ 高德和百度双API验证。

我的应用 | 高德控制台

控制台 | 百度地图开放平台

(2)密钥循环器

个人开发者key日限额5000次(免费),如果超出5000次的数据量 就要用到多个key(借同学同事的),可使用intertools.cycle创建密钥循环器。

(3)地址及辅助信息做拼接

根据需要调整ADDRESS_COLS地址拼接列,例如我需要用到“所在地”+“医疗机构名称”+“详细地址”拼接出原始地址,这样可以避免“详细地址”字段为空的情况。

(4)获取经纬度(地理编码)

  • 使用地图API的地理编码功能,获取:经度 | 纬度

  • 通过地图API获取:省 | 市 | 区 + 标准地址

(5)置信度检测与交叉验证

  • API置信度

  • 同时调用百度/腾讯API,对比经纬度偏差

(6)导出结果

  • 运行过程每10条显示进度信息

  • 导出EXCEL,保留了所有原始字段

  • 颜色标注关键状态列,对于偏差较大的结果可进行人工核验

代码

确保安装相关包:

pip install pandas requests geopy openpyxl
  • 适用于≤5000条数据的代码,单独高德API版 + 无交叉验证

import pandas as pd
import requests
from geopy.distance import geodesic
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
import time

# 配置参数
GAODE_KEY = '替换高德key'  # 替换为你的高德密钥

INPUT_FILE = r'C:\Users\User\Desktop\新建文件夹\副本.xlsx' #输入文件
OUTPUT_FILE = r'C:\Users\User\Desktop\新建文件夹\TEST.xlsx' #输出文件
SHEET_NAME = 'Sheet1'
ADDRESS_COLS = ['所在地', '医疗机构名称', '详细地址'] #拼接字段
RATE_LIMIT = 0.1  # 请求间隔(秒)

def gaode_geocode(address, api_key):
    """高德地理编码"""
    url = f"https://restapi.amap.com/v3/geocode/geo?address={address}&key={api_key}"
    try:
        response = requests.get(url, timeout=5)
        data = response.json()
        
        if data.get('status') == '1' and data.get('count') != '0':
            geo = data['geocodes'][0]
            province = geo.get('province', '')
            city = geo.get('city', province)  # 处理直辖市
            return {
                'gaode_省份': province,
                'gaode_城市': city,
                'gaode_区县': geo.get('district', ''),
                'gaode_标准地址': geo.get('formatted_address', ''),
                'gaode_经度': geo.get('location', '').split(',')[0] if geo.get('location') else '',
                'gaode_纬度': geo.get('location', '').split(',')[1] if geo.get('location') else '',
                'gaode_解析状态': '成功',
                'gaode_置信度': geo.get('level', '')
            }
        return {
            'gaode_省份': '',
            'gaode_城市': '',
            'gaode_区县': '',
            'gaode_标准地址': '',
            'gaode_经度': '',
            'gaode_纬度': '',
            'gaode_解析状态': f"失败: {data.get('info', '未知错误')}",
            'gaode_置信度': ''
        }
    except Exception as e:
        return {
            'gaode_省份': '',
            'gaode_城市': '',
            'gaode_区县': '',
            'gaode_标准地址': '',
            'gaode_经度': '',
            'gaode_纬度': '',
            'gaode_解析状态': f"异常: {str(e)}",
            'gaode_置信度': ''
        }

def validate_with_district_center(row):
    """行政区划中心验证"""
    if row['gaode_解析状态'] != '成功' or not row['gaode_经度']:
        return '无法验证'
    
    try:
        district = row['gaode_区县'] or row['gaode_城市'] or row['gaode_省份']
        url = f"https://restapi.amap.com/v3/config/district?keywords={district}&key={GAODE_KEY}"
        resp = requests.get(url, timeout=5)
        data = resp.json()
        
        if data['status'] == '1' and data['districts']:
            center = data['districts'][0]['center'].split(',')
            center_lng, center_lat = float(center[0]), float(center[1])
            target_lng = float(row['gaode_经度'])
            target_lat = float(row['gaode_纬度'])
            
            distance = geodesic((center_lat, center_lng), (target_lat, target_lng)).km
            if distance < 3:
                return f'准确(距中心{distance:.1f}km)'
            return f'偏差较大(距中心{distance:.1f}km)'
        return '获取中心失败'
    except:
        return '验证异常'

def process_excel(input_file, output_file, sheet_name, address_cols):
    """处理Excel主流程"""
    df = pd.read_excel(input_file, sheet_name=sheet_name)
    
    # 校验地址列
    missing_cols = [col for col in address_cols if col not in df.columns]
    if missing_cols:
        raise ValueError(f"缺少必要列: {missing_cols}")
    
    print(f"开始处理 {len(df)} 条记录...")
    results = []
    
    for index, row in df.iterrows():
        # 拼接地址
        address = ''.join(str(row[col]).strip() for col in address_cols if pd.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值