循环执行Reverse-Geo Coding失败问题及百万级数据处理求助
解决反向地理编码批量处理Google API的问题
看起来你碰到了Google Geocoding API批量处理时的经典限流问题——手动处理小文件没问题,自动化循环就歇菜,这多半是API的速率/配额限制在搞鬼!我来给你拆解问题和解决方案:
问题根源分析
Google Maps Geocoding API有严格的速率限制(每秒请求次数)和配额限制(每日请求总量):
- 手动处理1000条文件时,你自然的操作间隔(比如打开文件、等待响应的间隙)刚好避开了API的限流阈值;
- 自动化循环处理时,请求是连续发送的,瞬间就超过了API允许的每秒请求数,导致请求被拒绝、无响应或者返回空结果。
具体解决方案
1. 严格控制请求频率,匹配API速率限制
Google Geocoding API的免费版默认是每秒5次请求,付费版(Google Cloud)可提升至每秒50次(具体看你在控制台配置的配额)。循环处理时必须加入请求延迟:
import time def process_small_file(file_path): # 读取小文件数据 rows = load_csv(file_path) for row in rows: # 执行反向地理编码请求 zipcode = get_zipcode_from_latlon(row['lat'], row['lon']) # 控制请求频率:每秒5次的话,每次间隔0.2秒 time.sleep(0.2)
如果是付费版配额更高,可以适当缩短延迟,但绝对不要超过API规定的速率上限。
2. 实现指数退避的重试机制
当API返回429 Too Many Requests(限流)或者503 Service Unavailable(服务暂时不可用)时,不要直接放弃请求,用指数退避策略重试——每次失败后等待时间翻倍,直到成功或达到最大重试次数:
import time def get_zipcode_with_retry(lat, lon, max_retries=5): retries = 0 while retries < max_retries: try: response = send_geocode_request(lat, lon) if response.status_code == 200: # 从响应中提取邮政编码 return extract_zipcode(response.json()) elif response.status_code == 429: # 触发限流,等待后重试 wait_time = 2 ** retries # 1s, 2s, 4s, 8s... time.sleep(wait_time) retries += 1 else: # 其他错误,短时间后重试 time.sleep(1) retries += 1 except Exception as e: print(f"请求出错: {str(e)}") time.sleep(1) retries += 1 # 多次重试失败,返回空或标记为待处理 return None
3. 利用缓存避免重复请求
100万条数据里大概率有重复的经纬度,先对数据去重,再缓存已经获取到的邮编结果,既能减少API请求量,又能提升处理速度:
# 用字典缓存经纬度对应的邮编 zipcode_cache = {} def get_zipcode(lat, lon): # 先检查缓存 key = f"{lat}_{lon}" if key in zipcode_cache: return zipcode_cache[key] # 缓存没有,调用API获取 zipcode = get_zipcode_with_retry(lat, lon) if zipcode: zipcode_cache[key] = zipcode return zipcode
4. 使用官方批量处理方案
Google Cloud提供了更高效的批量地理编码方案,你可以:
- 在Google Cloud控制台启用Geocoding API,配置足够的配额;
- 使用官方的批量处理工具(比如通过Cloud Functions或者直接提交批量请求),这种方式比自己循环处理更稳定,也能更好地利用API配额。
5. 实时监控配额使用
在循环处理过程中,定时检查API的配额剩余量,避免因为配额耗尽导致后续请求全部失败。你可以通过Google Cloud的监控API或者控制台查看实时配额使用情况。
内容的提问来源于stack exchange,提问作者Adarsha Murthy
相关产品推荐
相关产品推荐

