You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大规模数据集经纬度转城市名出错,求替代代码方案

解决方案

方案1:优化Nominatim请求配置(缓解网络/限流问题)

如果不想换服务,先优化Nominatim的请求配置——它本身有严格的限流规则,默认超时太短,调整后能缓解大部分网络和限流问题:

import numpy as np
import geopy
import time
from geopy.exc import GeocoderTimedOut, GeocoderServiceError

def get_city_with_retry(row, geolocator, lat_field, lon_field, retries=5, delay=2):
    for attempt in range(retries):
        try:
            location = geolocator.reverse(
                (row[lat_field], row[lon_field]),
                exactly_one=True,
                timeout=10  # 延长超时时间,避免快速触发超时错误
            )
            if location and 'address' in location.raw:
                addr = location.raw['address']
                # 优先取city,其次town、village,都没有返回Unknown
                return addr.get('city', addr.get('town', addr.get('village', 'Unknown')))
            return 'Unknown'
        # 捕获常见的地理编码错误类型,避免无关异常中断重试
        except (GeocoderTimedOut, GeocoderServiceError, ConnectionError) as e:
            print(f"Attempt {attempt+1} failed for ({row[lat_field]}, {row[lon_field]}): {e}")
            time.sleep(delay * (2 ** attempt))  # 指数退避延迟,降低重复请求被限流的概率
        except Exception as e:
            print(f"Unexpected error for ({row[lat_field]}, {row[lon_field]}): {e}")
            break
    return 'Unknown'

# 初始化地理定位器,用户代理建议包含真实邮箱(符合Nominatim规范,降低被限流风险)
geolocator = geopy.Nominatim(
    user_agent='your-app-name/1.0 (your-email@example.com)',
    domain='nominatim.openstreetmap.org'
)

# 大规模数据分块处理,避免一次性请求触发限流
chunk_size = 100
for i in range(0, len(transactions_data), chunk_size):
    chunk = transactions_data.iloc[i:i+chunk_size]
    chunk['City'] = chunk.apply(
        lambda row: get_city_with_retry(row, geolocator, 'Latitude', 'Longitude'),
        axis=1
    )
    transactions_data.iloc[i:i+chunk_size] = chunk
    time.sleep(10)  # 块间停顿,给服务器缓冲时间

print(transactions_data)

方案2:切换到OpenCage地理编码服务(更稳定的免费商业服务)

如果Nominatim稳定性满足不了需求,换OpenCage服务是更省心的选择——它有每月2500次的免费请求额度,稳定性远高于公共Nominatim节点。

先安装依赖:pip install opencage

import numpy as np
import time
from opencage.geocoder import OpenCageGeocode
from opencage.exceptions import OpenCageError

def get_city_opencage(row, geocoder, lat_field, lon_field, retries=3):
    for _ in range(retries):
        try:
            results = geocoder.reverse_geocode(
                row[lat_field],
                row[lon_field],
                language='en',
                no_annotations=1  # 关闭额外注释,减少返回数据量
            )
            if results:
                components = results[0]['components']
                return components.get('city', components.get('town', components.get('village', 'Unknown')))
            return 'Unknown'
        except OpenCageError as e:
            print(f"Error for ({row[lat_field]}, {row[lon_field]}): {e}")
            time.sleep(2)
    return 'Unknown'

# 替换为你的OpenCage API密钥(官网免费申请即可)
API_KEY = 'your-opencage-api-key'
geocoder = OpenCageGeocode(API_KEY)

transactions_data['City'] = transactions_data.apply(
    lambda row: get_city_opencage(row, geocoder, 'Latitude', 'Longitude'),
    axis=1
)

print(transactions_data)

方案3:离线地理编码(完全摆脱网络依赖)

如果是超大规模数据或者无网络环境,直接用离线地理编码方案,彻底解决网络问题。需要先准备城市边界GeoJSON数据(可从GeoNames、OpenStreetMap提取)。

先安装依赖:pip install geopandas shapely

import geopandas as gpd
from shapely.geometry import Point

# 加载离线城市边界数据(替换为你下载的GeoJSON文件路径)
city_boundaries = gpd.read_file('city_boundaries.geojson')

# 将经纬度转换为Shapely Point对象
transactions_data['geometry'] = transactions_data.apply(
    lambda row: Point(row['Longitude'], row['Latitude']),
    axis=1
)

# 转换为GeoDataFrame,设置坐标系为WGS84(EPSG:4326)
gdf = gpd.GeoDataFrame(transactions_data, geometry='geometry', crs='EPSG:4326')

# 空间连接:匹配坐标到对应的城市边界
gdf = gpd.sjoin(gdf, city_boundaries, how='left', predicate='within')

# 提取城市名(根据你的GeoJSON文件字段调整,比如字段名可能是'name'或'city_name')
transactions_data['City'] = gdf['name'].fillna('Unknown')

# 清理临时生成的geometry列
transactions_data.drop('geometry', axis=1, inplace=True)

print(transactions_data)

关键提示

  • 使用Nominatim必须遵守规范:不要高频请求,用户代理要包含真实邮箱,避免触发限流。
  • OpenCage适合中小规模数据,免费额度足够日常使用,付费版支持更高并发。
  • 离线方案适合超大规模数据或无网络场景,需确保边界数据的准确性和时效性。

内容的提问来源于stack exchange,提问作者Anna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 20:15:19