【地理+python】调用第三方api进行地理编码/逆地理编码
一、高德
高德开放平台:https://lbs.amap.com/
免费配额:5000次/天
优势:地理编码可以直接获取citycode信息(从地址→经纬度→城市的过程可以一步到位)
1.地理编码(地址→经纬度→城市)
代码如下:
*调用key数量多个,所以用循环来区分每个key的调用额度。
# Purpose: 基于高德api实现地理编码
# Author: Shirley Lan
# Date: 2024-2-4
# Languages: Python
import pandas as pd
import requests
import os
# 读取文件夹
folder_path = "./data/"
file_list = os.listdir(folder_path)
print('begin')
output_path = './高德citycode/'
#定义调用的key
def amap_api_key(n):
key_list = ['xxxxxxxxxx', 'xxxxxxxxxx',
'xxxxxxxxxx', 'xxxxxxxxxx']
num = (n-1)//6
print(str(num))
amap_api_key = key_list[num]
print(str(amap_api_key))
return amap_api_key
# 定义高德地图API的请求函数
def get_location(address, api_key):
amap_api_key = api_key
url = f'https://restapi.amap.com/v3/geocode/geo?address={address}&key={amap_api_key}&city='
try:
response = requests.get(url)
data = response.json()
if data['status'] == '1' and int(data['count']) >= 1:
#location = data['geocodes'][0]['location'].split(',')
#latitude, longitude = map(float, location)
city_code = data['geocodes'][0]['citycode']
return city_code
else:
return None
except Exception as e:
print(f"Error: {e}")
return None
n=0
number = len(file_list)
if number > 24:
# 读取文件夹内的文件
for file in file_list:
n+= 1
print(amap_api_key(n))
api_key = amap_api_key(n)
print(f'现在读取第{n}个表格')
if file.endswith('.xlsx'):
file_path = os.path.join(folder_path, file)
print(str(file))
if n <= 20:
df = pd.read_excel(file_path)
# 遍历地址列,调用高德地图API并添加经纬度和城市代码列
df['高德城市代码'] = None
for index, row in df.iterrows():
address = row['address']
result = get_location(address, api_key)
if result:
city_code = result
# df.at[index, '经度'] = longitude
# df.at[index, '纬度'] = latitude
df.at[index, '高德城市代码'] = city_code
print(int(city_code))
# 将结果保存到新的 Excel 文件
output_file_path = os.path.join(output_path, file)
df.to_excel(output_file_path, index=False)
print(f"处理完成,结果保存到 {output_file_path}")
# 删除对应的表格
else:
break
else:
for file in file_list:
if file.endswith('.xlsx'):
file_path = os.path.join(folder_path, file)
print(str(file))
n += 1
print(amap_api_key(n))
api_key = amap_api_key(n)
print(f'现在读取第{n}个表格')
df = pd.read_excel(file_path)
# 遍历地址列,调用高德地图API并添加经纬度和城市代码列
df['高德城市代码'] = None
for index, row in df.iterrows():
address = row['address']
result = get_location(address, api_key)
if result:
city_code = result
# df.at[index, '经度'] = longitude
# df.at[index, '纬度'] = latitude
df.at[index, '高德城市代码'] = city_code
print(int(city_code))
# 将结果保存到新的 Excel 文件
output_file_path = os.path.join(output_path, file)
df.to_excel(output_file_path, index=False)
print(f"处理完成,结果保存到 {output_file_path}")
二、百度
百度开放平台:https://lbsyun.baidu.com/
配额:5000次/天(和高德地图一样)
劣势:地理编码只能获取输入地址的经纬度,没法再获取其他信息,比如城市等。
优势:相对高德好像准确度更高一些~
1.地理编码(地址→经纬度)
# Purpose: 基于百度api实现地理编码
# Author: Shirley Lan
# Date: 2024-2-4
# Languages: Python
import requests
import pandas as pd
# 你的百度地图API密钥
baidu_api_key = 'xxxxxx'
# 读取CSV文件
csv_file_path = './xxxx.csv'
df = pd.read_csv(csv_file_path)
print('yes')
print(df)
# 定义一个函数,用于调用百度地图API获取地址的经纬度信息
def get_location_coordinates(address):
url = f'http://api.map.baidu.com/geocoding/v3/?address={address}&output=json&ak={baidu_api_key}'
response = requests.get(url)
try:
result = response.json()
except requests.exceptions.JSONDecodeError as e:
print(f'JSON解析错误: {e}')
print(f'API返回的内容: {response.text}')
return None, None
if result['status'] == 0:
location = result['result']['location']
latitude = location.get('lat', None)
longitude = location.get('lng', None)
return latitude, longitude
else:
print(f'获取地址信息失败,错误代码:{result["status"]}')
return None, None
# 遍历地址列,并调用API获取经纬度信息
df['Latitude'] = ''
df['Longitude'] = ''
n=1
for index, row in df.iterrows():
address = row['address']
latitude, longitude = get_location_coordinates(address)
df.at[index, 'Latitude'] = latitude
df.at[index, 'Longitude'] = longitude
n=n+1
print(str(n))
# 将结果保存到新的excel文件
output_csv_file = './xxxxx.xlsx'
df.to_excel(output_csv_file)
print(f'经纬度信息已保存到 {output_csv_file}')
2.逆地理编码(经纬度→对应城市)
# Purpose: 基于百度api实现逆地理编码
# Author: Shirley Lan
# Date: 2024-2-4
# Languages: Python
import requests
import pandas as pd
# 你的百度地图API密钥
baidu_api_key = 'xxxxxxxx'
# 读取CSV文件
csv_file_path = './xxxx.csv'
df = pd.read_csv(csv_file_path, )
# 定义一个函数,用于逆地理编码获取经纬度对应的省和城市信息
def reverse_geocode(latitude, longitude):
url = f'http://api.map.baidu.com/reverse_geocoding/v3/?location={latitude},{longitude}&output=json&ak={baidu_api_key}'
response = requests.get(url)
try:
result = response.json()
except requests.exceptions.JSONDecodeError as e:
print(f'JSON解析错误: {e}')
print(f'API返回的内容: {response.text}')
return None, None
if result['status'] == 0:
address_components = result['result']['addressComponent']
province = address_components.get('province', '')
city = address_components.get('city', '')
return province, city
else:
print(f'逆地理编码失败,错误代码:{result["status"]}')
return None, None
# 遍历经纬度列,并调用API获取省和城市信息
df['Province'] = ''
df['City'] = ''
for index, row in df.iterrows():
latitude = row['Latitude']
longitude = row['Longitude']
if pd.notna(latitude) and pd.notna(longitude):
province, city = reverse_geocode(latitude, longitude)
df.at[index, 'Province'] = province
df.at[index, 'City'] = city
# 将结果保存到新的CSV文件
output_csv_file = '地址_with_geocoding_info.csv'
df.to_csv(output_csv_file, index=False)
print(f'省和城市信息已保存到 {output_csv_file}')
三、天地图
国家地理信息公共服务平台 天地图:https://www.tianditu.gov.cn/
配额:7000次/天(yyds)
优势:能够区分国内外地址(虽然只能查询到国内地址具体的城市信息)
劣势:需要地理编码+逆地理编码才能实现(地址→经纬度→城市)转变
因此,代码分为两个步骤
1.地理编码(地址→经纬度)
# Purpose: 基于天地图api实现地理编码
# Author: Shirley Lan
# Date: 2024-2-4
# Languages: Python
import requests
import pandas as pd
import time
import os
import json
# 你的天地图API密钥
tianditu_api_key = 'xxxxxxxxxxxx'
folder_path = "./xxxxxx/"
file_list = os.listdir(folder_path)
print('begin')
output_path = './xxxxx/'
# 定义一个函数,用于调用天地图API获取地址的经纬度信息
def get_location_info(address):
url = 'http://api.tianditu.gov.cn/geocoder?ds={"keyWord":"' + address + '"}&tk=' + tianditu_api_key
response = requests.get(url)
print(response)
if int(response.status_code) == 200:
print('yes')
try:
result = response.json()
time.sleep(1)
if 'status' in result:
if result['status'] == '0':
location = result['location']
print("location", location)
return location
else:
print(f'获取失败:{response.text}')
return None
else:
print(f'非正确响应格式:{response.text}')
return None
except requests.exceptions.JSONDecodeError as e:
print(f'JSON解析错误:{e},API返回内容:{response.text}')
return None
else:
print(f'获取地址信息失败,错误代码:{response.status_code}')
return None
n=0
for file in file_list:
n=n+1
print(f'准备地理编码第{n}个文件')
if n <= 8:
if file.endswith('.xlsx'):
file_path = os.path.join(folder_path, file)
print(str(file))
df = pd.read_excel(file_path)
time.sleep(1)
# 遍历地址列,并调用API获取经纬度信息
df['tianditu_Latitude'] = ''
df['tianditu_Longitude'] = ''
for index, row in df.iterrows():
address = row['address']
time.sleep(1)
location = get_location_info(address)
if location:
df.at[index, 'tianditu_Latitude'] = location['lat']
df.at[index, 'tianditu_Longitude'] = location['lon']
# 将结果保存到新的CSV文件
output_excel_file = os.path.join(output_path, file)
df.to_excel(output_excel_file, index=False)
print(f'经纬度信息已保存到 {output_excel_file}')
os.remove(file_path)
else:
continue
else:
break
2.逆地理编码(经纬度→对应省市区)
# Purpose: 基于天地图api实现逆地理编码
# Author: Shirley Lan
# Date: 2024-2-4
# Languages: Python
import requests
import pandas as pd
import time
import os
import json
folder_path = "./xxxx/"
file_list = os.listdir(folder_path)
print('begin')
output_path = './xxxxxx/'
def tianditu_api_key(n):
key_list = ['xxxxxxxxxxx','xxxxxxxxxxxxx','xxxxxxxxxxxxxxx']
num = n//8
print(num)
tianditu_api = key_list[num]
return tianditu_api
# 定义一个函数,用于调用天地图API获取地址的经纬度信息
def get_location_info(lon,lat,tianditu_api):
url = 'http://api.tianditu.gov.cn/geocoder?postStr={"lon":' + str(lon) + ',"lat":"'+str(lat)+'","ver":1}&type=geocode&tk=' + tianditu_api
response = requests.get(url)
print(response)
if int(response.status_code) == 200:
print('yes')
try:
result = response.json()
time.sleep(1)
if 'status' in result:
if result['status'] == '0':
location = result['result']["addressComponent"]
print("location", location)
return location
else:
print(f'获取失败:{response.text}')
return None
else:
print(f'非正确响应格式:{response.text}')
return None
except requests.exceptions.JSONDecodeError as e:
print(f'JSON解析错误:{e},API返回内容:{response.text}')
return None
else:
print(f'获取地址信息失败,错误代码:{response.status_code}')
return None
n=-1
for file in file_list:
n=n+1
print(f'准备地理编码第{n}个文件')
if n <= 24:
if file.endswith('.xlsx'):
file_path = os.path.join(folder_path, file)
print(str(file))
df = pd.read_excel(file_path)
time.sleep(1)
tianditu_api = tianditu_api_key(n)
# 遍历地址列,并调用API获取经纬度信息
df['tianditu_city'] = ''
df['tianditu_county'] = ''
df['tianditu_province'] = ''
for index, row in df.iterrows():
lat = row['tianditu_Latitude']
lon = row['tianditu_Longitude']
time.sleep(1)
location = get_location_info(lon,lat,tianditu_api)
if location:
df.at[index, 'tianditu_city'] = location['city']
df.at[index, 'tianditu_county'] = location['county']
df.at[index, 'tianditu_province'] = location['province']
# 将结果保存到新的CSV文件
output_excel_file = os.path.join(output_path, file)
df.to_excel(output_excel_file, index=False)
print(f'城市信息已保存到 {output_excel_file}')
os.remove(file_path)
else:
continue
else:
break
#高德#百度#天地图#地理编码#逆地理编码
作者:EH_snow