如何基于地址获取经纬度与完整地址?解决Nominatim报错403问题
解决Geopy Nominatim 403错误并批量解析地址经纬度
修复403权限不足错误
你碰到的GeocoderInsufficientPrivileges(403错误),核心原因是Nominatim对请求的user-agent标识有严格要求,通用的myGeocoder这类名称会被服务器判定为不合法请求;另外短时间内频繁请求也会触发限流机制。
修复要点:
- 更换
user-agent为带辨识度的格式,建议包含你的项目名称和联系方式(比如邮箱),让服务器识别请求来源的合法性 - 添加请求间隔,避免短时间内发送大量请求
- 处理地址解析失败的边界情况(比如地址无法识别时返回
None)
修改后的单地址测试代码:
from geopy.geocoders import Nominatim import time # 替换成你的项目名和真实邮箱 geolocator = Nominatim(user_agent="my-address-geocoder/1.0 (your-email@example.com)") time.sleep(1) # 每次请求间隔1秒,符合Nominatim使用规则 location = geolocator.geocode("apple fifth avenue new york") if location: address = location.address latitude = location.latitude longitude = location.longitude print(latitude, longitude, address) else: print("地址无法解析")
批量处理DataFrame中的地址
针对包含address_1列的DataFrame,我们可以封装一个解析函数,批量处理所有地址并生成经纬度和完整地址列:
import pandas as pd from geopy.geocoders import Nominatim import time # 初始化地理编码器,使用规范的user-agent geolocator = Nominatim(user_agent="my-address-geocoder/1.0 (your-email@example.com)") def geocode_address(address): # 处理空值或空白地址 if pd.isna(address) or address.strip() == "": return (None, None, None) time.sleep(1) # 强制延迟,避免触发限流 try: location = geolocator.geocode(address) if location: return (location.latitude, location.longitude, location.address) else: return (None, None, None) except Exception as e: print(f"解析地址'{address}'时出错: {str(e)}") return (None, None, None) # 示例DataFrame(替换成你的实际数据) data = { "address_1": [ "apple fifth avenue new york", "burj khalifa dubai", "microsoft office san francisco" ] } df = pd.DataFrame(data) # 批量解析并生成新列 df[["latitude", "longitude", "full_address"]] = df["address_1"].apply( lambda x: pd.Series(geocode_address(x)) ) print(df)
关键注意事项
- Nominatim仅对非商业用途免费开放,必须严格遵守请求频率限制(至少1秒1次请求),禁止批量抓取大规模数据
- 如果需要更高的请求效率或商业使用,可考虑使用付费地理编码服务
- 必须处理异常和空值,避免单个地址解析失败导致整个程序崩溃
内容的提问来源于stack exchange,提问作者french_fries
相关产品推荐
相关产品推荐

