使用天地图API进行地址转经纬度完整教程
一、教程概述
本教程将指导您如何使用国家地理信息公共服务平台(天地图)的API服务,将结构化地址转换为经纬度坐标。通过学习本教程,您将能够:
- 申请天地图开发者账号和API密钥
- 理解地理编码的基本概念
- 使用Python调用天地图地理编码API
- 批量处理Excel中的地址数据
- 解析和保存地理编码结果
- 通过Folium库进行地理编码地图可视化
二、前期准备
1. 注册天地图开发者账号
访问天地图开放平台:
- 点击"开发者注册"
- 填写必要信息完成账号注册
- 登录后进入"控制台"
2. 申请API密钥
- 在控制台选择"我的应用" → “创建新应用”
- 填写应用信息(如应用名称、类型等)
- 获取分配的API Key(形如:
4fdfe********955
)
3. 开发环境准备
确保已安装:
- Python 3.6+
- 以下Python库:
pip install requests pandas openpyxl
三、基础API调用
1. 官网API接口参数
2. 单个地址转换示例
import requests
import json
def tianditu_geocode(address, api_key):
"""
天地图地理编码API调用
:param address: 结构化地址字符串
:param api_key: 天地图API密钥
:return: 经纬度字典{'lon':经度, 'lat':纬度} 或None
"""
url = f'http://api.tianditu.gov.cn/geocoder?ds={{"keyWord":"{address}"}}&tk={api_key}'
try:
response = requests.get(url)
data = response.json()
if data.get('status') == '0': # 请求成功
return {
'lon': data['location']['lon'],
'lat': data['location']['lat'],
'level': data['location'].get('level', '')
}
else:
print(f"请求失败: {data.get('msg')}")
return None
except Exception as e:
print(f"请求异常: {str(e)}")
return None
# 使用示例
if __name__ == "__main__":
API_KEY = "您的API密钥" # 替换为实际密钥
test_address = "北京市海淀区莲花池西路28号"
result = tianditu_geocode(test_address, API_KEY)
if result:
print(f"地址坐标: 经度={result['lon']}, 纬度={result['lat']}")
print(f"匹配级别: {result['level']}")
3. 参数说明
参数 | 必选 | 说明 |
---|---|---|
keyWord | 是 | 结构化地址信息 |
tk | 是 | 开发者密钥 |
level | 否 | 匹配级别(返回字段) |
4. 返回结果示例
成功响应:
{
"status": "0",
"location": {
"lon": "116.301934",
"lat": "39.992576",
"level": "门牌号"
}
}
失败响应:
{
"status": "1",
"msg": "无查询结果"
}
四、批量处理Excel数据
1. 完整批量处理脚本
import pandas as pd
import time
from tqdm import tqdm # 进度条工具
def batch_geocode(input_file, output_file, api_key, address_column='地址'):
"""
批量处理Excel中的地址
:param input_file: 输入Excel路径
:param output_file: 输出Excel路径
:param api_key: 天地图API密钥
:param address_column: 地址列名
"""
try:
# 读取Excel文件
df = pd.read_excel(input_file)
# 初始化结果列
df['经度'] = ''
df['纬度'] = ''
df['匹配级别'] = ''
df['状态'] = '未处理'
# 创建进度条
with tqdm(total=len(df), desc="处理进度") as pbar:
for index, row in df.iterrows():
address = str(row[address_column]).strip()
if not address or address == 'nan':
df.at[index, '状态'] = '地址为空'
pbar.update(1)
continue
# 调用API
result = tianditu_geocode(address, api_key)
# 处理结果
if result:
df.at[index, '经度'] = result['lon']
df.at[index, '纬度'] = result['lat']
df.at[index, '匹配级别'] = result['level']
df.at[index, '状态'] = '成功'
else:
df.at[index, '状态'] = '查询失败'
# 更新进度
pbar.update(1)
# 遵守API调用频率限制(10次/秒)
if index < len(df) - 1:
time.sleep(0.1)
# 保存结果
df.to_excel(output_file, index=False)
print(f"\n处理完成!结果已保存到: {output_file}")
except Exception as e:
print(f"\n处理过程中出错: {str(e)}")
if __name__ == "__main__":
# 配置参数
CONFIG = {
"input_file": "地址数据.xlsx",
"output_file": "地理编码结果.xlsx",
"api_key": "您的API密钥",
"address_column": "地址" # 根据实际Excel列名调整
}
# 执行批量处理
batch_geocode(**CONFIG)
2. Excel文件格式要求
输入文件示例(地址数据.xlsx):
序号 | 地址 |
---|---|
1 | 北京市海淀区中关村南大街5号 |
2 | 上海市浦东新区陆家嘴环路1288号 |
输出文件示例(地理编码结果.xlsx):
序号 | 地址 | 经度 | 纬度 | 匹配级别 | 状态 |
---|---|---|---|---|---|
1 | 北京市海淀区… | 116.320338 | 39.984702 | 门牌号 | 成功 |
2 | 上海市浦东新区… | 121.502471 | 31.245329 | 门牌号 | 成功 |
五、常见问题解决
1. API调用失败排查
问题现象 | 可能原因 | 解决方案 |
---|---|---|
返回"无权限" | API密钥无效 | 检查密钥是否正确,在控制台重新生成 |
频繁失败 | 超过调用频率限制 | 确保每次调用间隔≥1秒 |
部分地址失败 | 地址格式不规范 | 检查地址是否完整准确 |
连接超时 | 网络问题 | 检查网络连接,尝试使用代理 |
2. 性能优化建议
-
缓存机制:对重复地址可建立本地缓存
cache = {} if address in cache: return cache[address]
-
多线程处理(需申请更高权限):
from concurrent.futures import ThreadPoolExecutor with ThreadPoolExecutor(max_workers=5) as executor: results = list(executor.map(geocode_function, addresses))
-
断点续传:处理大文件时可保存进度
if os.path.exists('progress.json'): with open('progress.json') as f: progress = json.load(f)
六、进阶应用
1. 地理编码结果可视化
使用Folium库创建交互式地图:
import folium
def visualize_results(output_file):
success_df = pd.read_excel(output_file)
# 创建地图中心点
center_lat = success_df['纬度'].astype(float).mean()
center_lon = success_df['经度'].astype(float).mean()
m = folium.Map(location=[center_lat, center_lon], zoom_start=12)
# 添加天地矢量图底图
folium.TileLayer(
tiles='http://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=api_key',# 替换为实际密钥
attr='天地图',
name='天地矢量图',
subdomains='0123',
overlay=False,
control=True
).add_to(m)
# 添加天地矢量图标注图层
folium.TileLayer(
tiles='http://t{s}.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=api_key',# 替换为实际密钥
attr='天地图标注',
name='天地矢量图标注',
subdomains='0123',
overlay=True,
control=True
).add_to(m)
# 添加标记点
for _, row in success_df.iterrows():
folium.Marker(
location=[row['纬度'], row['经度']],
popup=row['地址'],
icon=folium.Icon(color='blue')
).add_to(m)
# 保存地图
m.save('地理编码可视化.html')
print("可视化地图已生成")
七、注意事项
-
API使用限制:
- 免费版通常有每日调用限额(如7000次/天)
- 商用需申请企业授权
-
地址规范建议:
- 采用"省+市+区+街道+门牌号"的完整结构
- 避免使用简称(如"京"代替"北京")
- 特殊地址需人工校验
-
数据安全:
- 不要将API密钥提交到公开代码库
- 敏感地址数据需加密处理
-
坐标系统说明:
- 天地图使用WGS84坐标系统
- 与其他地图服务对接时注意坐标转换
八、资源链接
通过本教程,您应该已经掌握了使用天地图API进行地址转经纬度的完整流程。如需进一步帮助,可以参考官方文档或加入开发者社区交流。实际应用中,建议先进行小规模测试,确认结果符合预期后再进行批量处理。