【地理+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

物联沃分享整理
物联沃-IOTWORD物联网 » 【地理+python】调用第三方api进行地理编码/逆地理编码

发表回复