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

9万条地址调用Google Geocoder API:iterrows/itertuples失效求助

问题根源拆解

  • IndexError:和iterrows()无关,核心是Google Geocoder API返回的response['results']为空列表——要么是单条地址格式无效无法解析,要么是9万条请求触发了API的速率/配额限制,导致API返回空结果。
  • itertuples()的ValueError:itertuples()返回的是namedtuple实例,不是(i, row)的二元组,强行拆成两个变量必然报错。正确用法是遍历每个tuple,通过属性访问字段。
  • itertuples()的KeyError:你大概率还是用了df.at[i, ...]的写法,但itertuples()的元素不是索引值,用它当键访问DataFrame自然会触发KeyError。

修复后的完整代码方案

import requests
import pandas as pd
import time
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# 初始化带重试机制的会话,应对API限流/服务器错误
session = requests.Session()
retry = Retry(
    total=5,  # 最多重试5次
    backoff_factor=1,  # 重试间隔:1s→2s→4s...
    status_forcelist=[429, 500, 502, 503, 504]  # 遇到这些状态码自动重试
)
adapter = HTTPAdapter(max_retries=retry)
session.mount("https://", adapter)
session.mount("http://", adapter)

API_KEY = "你的API密钥"
base_url = "https://maps.googleapis.com/maps/api/geocode/json"

# 读取数据集
df = pd.read_excel("你的地址文件.xlsx")

# 提前初始化坐标列,避免循环中动态添加的性能开销
df['Geo_Lat_New'] = None
df['Geo_Lng_New'] = None

# 使用itertuples遍历,性能远高于iterrows
for row in df.itertuples(index=True):  # index=True保留行索引
    idx = row.Index
    # 拼接地址,自动过滤空值,避免生成",,城市"这类无效格式
    address_parts = [
        str(row.adresse1) if pd.notna(row.adresse1) else "",
        str(row.postnr) if pd.notna(row.postnr) else "",
        str(row.By) if pd.notna(row.By) else ""
    ]
    apiAddress = ",".join(part for part in address_parts if part.strip())
    
    # 跳过空地址
    if not apiAddress.strip():
        print(f"行{idx}地址为空,跳过")
        continue
    
    parameters = {
        'key': API_KEY,
        'address': apiAddress
    }
    
    try:
        response = session.get(base_url, params=parameters).json()
        
        # 先检查API返回状态,避免直接取results[0]报错
        if response.get('status') != 'OK':
            print(f"行{idx}处理失败,状态:{response.get('status')},地址:{apiAddress}")
            continue
        
        # 提取坐标
        geometry = response['results'][0]['geometry']
        lat = geometry['location']['lat']
        lng = geometry['location']['lng']
        
        # 写入数据
        df.at[idx, 'Geo_Lat_New'] = lat
        df.at[idx, 'Geo_Lng_New'] = lng
        
        # 速率控制:免费版配额是每秒5次,付费版可提至每秒50次,按需调整
        time.sleep(0.2)
    
    except Exception as e:
        print(f"行{idx}发生异常:{str(e)},地址:{apiAddress}")
        continue

# 保存结果
df.to_excel("带坐标的地址文件.xlsx", index=False)
print(df.head(10))

关键优化说明

  1. 异常防护:
    • 检查API返回的status字段(比如ZERO_RESULTS表示地址无法解析,OVER_QUERY_LIMIT表示配额耗尽),避免直接访问空列表报错。
    • 全局异常捕获,单个地址处理失败不会中断整个批量任务,同时记录错误信息方便后续排查。
  2. itertuples正确用法:
    • 开启index=True获取行索引,用df.at[idx, ...]写入数据,避免KeyError。
    • 通过tuple属性名(如row.adresse1)访问字段,比df.at访问效率更高。
  3. API请求稳定性:
    • 带重试的会话:遇到限流、服务器错误时自动重试,减少请求失败率。
    • 速率控制:time.sleep(0.2)确保不超过API的请求频率限制,付费用户可缩短间隔。
  4. 数据预处理:
    • 过滤空地址字段,避免生成无效的API请求参数。
    • 提前初始化坐标列,降低循环中的性能开销。

额外注意事项

  • 检查Google Cloud配额:Geocoder API免费版每天仅2500次请求,9万条数据必须升级付费配额,否则会触发OVER_QUERY_LIMIT。
  • 考虑批量请求:API支持最多50个地址/批量请求,能大幅减少总请求次数,提升处理效率(需调整请求格式为batch模式)。
  • 缓存重复地址:如果数据中有大量重复地址,可先缓存已解析的坐标,避免重复请求浪费配额。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:55:21