天天看点

基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标

前言

  • 本博客主要的内容是集成了多个博主和参考网站的代码,实现了基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标一整套体系流程,文章后面会附上相应作者文章的链接,若有侵权,请联系我修改。

1、百度地图开放平台创建web服务应用

  • 百度开放平台的网站百度地图开放平台
  • 创建新的应用之前你需要申请一个账号,并且通过认证。
  • 点击控制台–>应用管理–>我的应用–>创建应用,其中应用类型选择服务端,启用的服务默认全部选中即可,请求校验方式选用IP白名校验,0.0.0.0表示不对IP做任何限制,在测试阶段可以设置为该IP,应用正式上线后建议修改。
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标

2、基于web服务api爬取对应地点的经纬度

  • 我的本意是做一个丝绸之路的路线图,因此爬取经纬的地点都是丝绸之路上的地点,原始数据存储以如下格式存储在excel中。
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标
  • 经纬度的爬取在网上有很多现场的代码,我直接附上就好了,代码也没啥好讲的,代码运行环境是annaconda的jupyter笔记本。
import urllib
import math
import pandas as pd
import requests
import json
def BaiduQuery(address, currentkey):
    url = 'http://api.map.baidu.com/geocoder/v2/'
    params = { 'address' : address,           
               'ak' : currentkey, # 百度密钥
               'output': 'json'     }  # 输出结果设置为json格式
    res = requests.get(url,params)
    jd = json.loads(res.text)    
    # 将json格式转化为Python字典
    #搜索不到的地点经纬度坐标设置为0,0
    if jd['status'] == 1:
        coords = {'lng': 0, 'lat': 0}
    else:
    #百度坐标转火星坐标
        coords = jd['result']['location']
        coords_1 = baidu_togcj02(coords['lng'], coords['lat'])
        coords['lng'] = coords_1[0]['x']
        coords['lat'] = coords_1[0]['y']
     #火星坐标转WGS84
        reverses_coord = gcj02_to_wgs84(coords['lng'], coords['lat'])
        coords['lng'] = reverses_coord[0]
        coords['lat'] = reverses_coord[1]
    return coords
           
  • 可能细心的读者以及发现了我这篇博客的坐标转了两次,一次是转成火星坐标(GCJ02),一次是从火星坐标转成WGS84,原因在下面我会解答。

3、百度坐标转换参数介绍

  • web服务端的坐标转换限制很大,是通过(http://api.map.baidu.com/geoconv/v1/?)网站获取对应的转换结果,网站的完整请求方式如下
  • ‘http://api.map.baidu.com/geoconv/v1/?coords=’+data+’&from=5&to=3&output=json’+’&ak=yourak’
  • 上述中data是一个坐标对,形式如"66.968649,39.656794",ad就是创建应用生成的AK,主要参数是from和to,表示初始坐标系和目标坐标系。
  • from:number //源坐标类型,分别有:

    1:GPS设备获取的角度坐标,WGS84坐标;

    2:GPS获取的米制坐标、sogou地图所用坐标;

    3:google地图、soso地图、aliyun地图、mapabc地图和amap地图所用坐标,国测局(GCJ02)坐标;

    4:3中列表地图坐标对应的米制坐标;

    5:百度地图采用的经纬度坐标;

    6:百度地图采用的米制坐标;

    7:mapbar地图坐标;

    8:51地图坐标

  • to:number //目标坐标类型,分别有:

    3:国测局(GCJ02)坐标;

    4:3中对应的米制坐标;

    5:bd09ll(百度经纬度坐标);

    6:bd09mc(百度米制经纬度坐标)

  • 可以看出百度坐标转换web服务api不支持百度坐标直接到WGS84的转换,但是可以转换成火星坐标,而正好网上有很多火星坐标到WGS84的转换方法,并且是公开的公式,公开方不明,精度保障有限,科研慎用。
  • 接下来又是代码了,代码是从百度坐标转成火星坐标的方法。
def baidu_togcj02(lng, lat):
    data = str(lng)+','+str(lat)
    url = 'http://api.map.baidu.com/geoconv/v1/?coords='+data+'&from=5&to=3&output=json'+'&ak=sHlqv5QdGaZzeIcpAT2gbVe8aFevOpXm'
    response = requests.get(url) #发出请求
    answer = response.json() #json化   
    coords = answer['result']
    return coords
           
  • 注意:该方法返回的是一个列表,列表的第一项是一个包含坐标对的字典,以x、y为key,所以引用的方式为coords_1[0][‘x’]和 coords_1[0][‘y’]

4、火星坐标转WGS84

  • 直接上代码吧,也没啥好说的,火星坐标对国外的坐标没有偏移,因此国外的坐标不需要进行变化。
pi = math.pi  # π
x_pi = pi * 3000.0 / 180.0
a = 6378245.0  # 长半轴
ee = 0.00669342162296594323  # 偏心率平方
def gcj02_to_wgs84(lng, lat):
    """
    GCJ02(火星坐标系)转GPS84
    :param lng:火星坐标系的经度
    :param lat:火星坐标系纬度
    :return:
    """
    if out_of_china(lng, lat):
        return [lng, lat]
    dlat = _transformlat(lng - 105.0, lat - 35.0)
    dlng = _transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * pi
    magic = math.sin(radlat)
    magic = 1 - ee * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)
    dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [lng * 2 - mglng, lat * 2 - mglat]


def _transformlat(lng, lat):
    ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + \
          0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lat * pi) + 40.0 *
            math.sin(lat / 3.0 * pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *
            math.sin(lat * pi / 30.0)) * 2.0 / 3.0
    return ret


def _transformlng(lng, lat):
    ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + \
          0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))
    ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *
            math.sin(2.0 * lng * pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(lng * pi) + 40.0 *
            math.sin(lng / 3.0 * pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *
            math.sin(lng / 30.0 * pi)) * 2.0 / 3.0
    return ret


def out_of_china(lng, lat):
    """
    判断是否在国内,不在国内不做偏移
    :param lng:
    :param lat:
    :return:
    """
    return not (lng > 73.66 and lng < 135.05 and lat > 3.86 and lat < 53.55)
           
  • 上面是方法,测试代码如下
coords = BaiduQuery('碎叶', currentkey="AK")
print(coords)
df = pd.read_excel('丝绸之路城市表.xlsx')
height,width = df.shape
print(df.head(3))
for i in range(0, height):
    coords = BaiduQuery(df['city'][i], currentkey="AK")
    df['lng'][i] = coords['lng']
    df['lat'][i] = coords['lat']
#导出结果到Excel
df.to_excel('city_coords.xls')
print("数据爬取成功,已存储!")
           
  • 爬取结果如下所示:
    基于百度地图开放平台Web服务api爬取经纬度并转换为WGS84坐标
  • 参考博客:

    1 :Python源码|GCJ02转WGS84坐标

    2:百度地图js 坐标转换

    3:Python调用百度地图API爬取经纬度