Python脚本遍历地址表调用Google API地理编码并写入经纬度至对应行
看起来你卡在了遍历数据表并更新行的环节上——这其实是ArcPy游标使用的典型场景,我来帮你把代码补全并解释清楚:
完整可运行代码
import urllib.request import urllib.parse import json import time import arcpy # 设置工作空间和数据表路径 arcpy.env.workspace = "D:/GIS/" table_path = "addr.dbf" # 替换为你的Google API密钥 GOOGLE_API_KEY = "YOUR_GOOGLE_API_KEY" def geocode_address(address): """调用Google地理编码API,返回(纬度, 经度),失败则返回(None, None)""" if not address: print("空地址,跳过") return (None, None) base_url = "https://maps.googleapis.com/maps/api/geocode/json?" # 编码地址参数,避免特殊字符导致请求失败 encoded_address = urllib.parse.quote(address) params = f"address={encoded_address}&key={GOOGLE_API_KEY}" full_url = base_url + params try: response = urllib.request.urlopen(full_url) data = json.load(response) if data['status'] == 'OK': location = data['results'][0]['geometry']['location'] return (location['lat'], location['lng']) else: print(f"地址「{address}」编码失败,状态: {data['status']}") return (None, None) except Exception as e: print(f"请求地址「{address}」时出错: {str(e)}") return (None, None) # 自动检查并创建经纬度存储字段(如果不存在) field_names = [f.name.upper() for f in arcpy.ListFields(table_path)] if 'LAT' not in field_names: arcpy.AddField_management(table_path, "LAT", "DOUBLE") if 'LON' not in field_names: arcpy.AddField_management(table_path, "LON", "DOUBLE") # 替换为你数据表中存储地址的字段名(比如"FULL_ADDR") address_field = "ADDRESS" # 使用UpdateCursor遍历每行并更新经纬度 with arcpy.da.UpdateCursor(table_path, [address_field, "LAT", "LON"]) as cursor: for row in cursor: current_address = row[0] # 调用地理编码函数获取坐标 lat, lon = geocode_address(current_address) # 更新当前行的经纬度值 row[1] = lat row[2] = lon # 提交更新到数据表 cursor.updateRow(row) # 加入延迟,避免触发Google API请求频率限制 time.sleep(0.2) print("所有地址的经纬度更新完成!")
关键细节解释
- 高效游标使用:用
arcpy.da.UpdateCursor(数据访问模块的游标)替代旧版游标,它不仅速度更快,还支持直接修改行数据,配合with语句能自动管理资源,不用手动关闭游标。 - 字段自动处理:先检查表中是否有
LAT和LON字段,没有则自动创建,避免因缺少字段报错。 - 地址编码处理:用
urllib.parse.quote处理地址中的特殊字符(比如空格、中文、逗号),确保API请求的格式合法。 - 错误捕获机制:加入
try-except块捕获网络请求异常,同时处理API返回的错误状态(比如ZERO_RESULTS、OVER_QUERY_LIMIT),方便你排查问题。 - 请求频率控制:Google地理编码API免费版有每秒5次的请求限制,加入
time.sleep(0.2)控制请求间隔,避免被临时封禁。
注意事项
- 一定要把
YOUR_GOOGLE_API_KEY替换成你自己的有效密钥,并且确保已经在Google Cloud控制台启用了地理编码API。 - 把
address_field替换成你数据表中实际存储地址的字段名(比如"STREET_ADDR"、"FULL_ADDRESS")。如果你的地址分散在多个字段(比如街道、城市、邮编),可以拼接后传入函数:current_address = f"{row[0]}, {row[1]}, {row[2]}"。 - 如果你的地址数量很大(比如超过1000条),建议考虑使用Google的批量地理编码服务,或者升级到付费版API,避免触发请求限制。
内容的提问来源于stack exchange,提问作者evand




