如何用Python完成百度与高德地图转换

AI 摘要 / TL;DR

众所周知,Python的一个使用场景还是比较多的,在工作当中,也会涉及到多方面的一些事情。那么,今天小编写这篇文章的一个主要目的,给大家来介绍关于如何用Python完成百度与搞得地图转换,下面就给大家详细介绍下。 一、地理编码与逆编码 地理编码与逆编码表示的是地名地址与地理坐标(经纬度)互相转换的过程。其中,将地址信息

来源: https://www.ucloud.cn/yun/128237.html 作者: 89542767 发布日期: 发布于2022-11-04 14:13

众所周知,Python的一个使用场景还是比较多的,在工作当中,也会涉及到多方面的一些事情。那么,今天小编写这篇文章的一个主要目的,给大家来介绍关于如何用Python完成百度与搞得地图转换,下面就给大家详细介绍下。

一、地理编码与逆编码

  地理编码与逆编码表示的是地名地址与地理坐标(经纬度)互相转换的过程。其中,将地址信息映射为地理坐标的过程称之为地理编码;将地理坐标转换为地址信息的过程称之为逆地理编码。(ps:猜猜我在哪)

01.png

  地理编码能对一些只有名称或地址的数据进行空间化,从而可以开展空间分析和制图,对于数据分析人员十分重要。

  大量地图厂商都提供了相关的API,可以直接利用这些API进行转化。国外的如谷歌、esri、osm等,国内的有百度、高德、腾讯等公司,python提供了专业的geopy包集成了这些API调用。

  地理处理包将多带带研究,本文直接使用高德和百度的开放API进行地理编码。使用开放API前需要注册应用获取KEY

  提示:以下是本篇文章正文内容,下面案例可供参考

二、高德地图地理编码

  详细信息可参考官方开发文档,可以看到,请求参数必填的有key和address,其他的根据需要设置

02.png

  具体代码如下:

  def getGDCor(key,addr):
  baseUrl='http://restapi.amap.com/v3/geocode/geo?'
  params={'key':key,##应用key
  'address':addr,
  'city':u'武汉'##指定城市,限制范围
  }
  url=baseUrl+urllib.parse.urlencode(params)
  req=urllib.request.Request(url)
  content=urllib.request.urlopen(req).read()
  jsonData=json.loads(content)
  lon,lat='',''
  if jsonData['status']=='1':
  try:
  corr=jsonData['geocodes'][0]['location']
  lon,lat=corr.split(',')[0],corr.split(',')[1]
  except:
  lon,lat='0','0'
  else:
  print('error')
  return(lon,lat)

三、百度地图地理编码

  百度地图与高德类似,同样需要注册应用获取key,详细内容参考官网文档

  def getBDCor(ak,addr):
  #sleep(random.random())
  baseUrl='http://api.map.baidu.com/geocoding/v3/?'
  params={'address':addr,
  'city':u'武汉市',
  'output':'json',
  'ak':ak,##应用key
  'callback':'showLocation'
  }
  url=baseUrl+urllib.parse.urlencode(params)
  req=urllib.request.urlopen(url).read().decode()#'utf-8'针对中文需要设施编码
  cont1=req.replace("showLocation&&showLocation(",'')
  cont=cont1.replace(")",'')
  jsonData=json.loads(cont)
  lon,lat=0,0
  if jsonData['status']==0:
  try:
  lon=jsonData['result']['location']['lng']
  lat=jsonData['result']['location']['lat']
  except:
  print(addr)
  return(lon,lat)

  四、坐标转换和空间化

  高德或百度获取的地理位置都是经过加密的,高德地图位置使用的是火星坐标,百度地图是bd-09坐标,与WGS84坐标系间有偏差,通常需要进行转换。

  火星坐标(GCJ-02):国测局坐标,由WGS-84加密而成,国内必须至少使用GCJ-02坐标系,或者使用在GCJ-02加密后再进行加密的坐标系,如百度坐标系。高德和Google在国内都是使用GCJ-02坐标系,可以说,GCJ-02是国内最广泛使用的坐标系;

  百度坐标系是在GCJ-02坐标系的基础上再次加密偏移后形成的坐标系。

  各坐标间可以通过坐标转换互转,通常有三参数或七参数法,网上可找到相关的转换参数,贴一下转换函数(不知道哪位大神写的)

  import math
  x_pi=3.14159265358979324*3000.0/180.0
  pi=3.1415926535897932384626#π
  a=6378245.0#长半轴
  ee=0.00669342162296594323#扁率
  def gcj02_to_bd09(lng,lat):
  """
  火星坐标系(GCJ-02)转百度坐标系(BD-09)
  谷歌、高德——>百度
  :param lng:火星坐标经度
  :param lat:火星坐标纬度
  :return:
  """
  z=math.sqrt(lng*lng+lat*lat)+0.00002*math.sin(lat*x_pi)
  theta=math.atan2(lat,lng)+0.000003*math.cos(lng*x_pi)
  bd_lng=z*math.cos(theta)+0.0065
  bd_lat=z*math.sin(theta)+0.006
  return[bd_lng,bd_lat]
  def bd09_to_gcj02(bd_lon,bd_lat):
  """
  百度坐标系(BD-09)转火星坐标系(GCJ-02)
  百度——>谷歌、高德
  :param bd_lat:百度坐标纬度
  :param bd_lon:百度坐标经度
  :return:转换后的坐标列表形式
  """
  x=bd_lon-0.0065
  y=bd_lat-0.006
  z=math.sqrt(x*x+y*y)-0.00002*math.sin(y*x_pi)
  theta=math.atan2(y,x)-0.000003*math.cos(x*x_pi)
  gg_lng=z*math.cos(theta)
  gg_lat=z*math.sin(theta)
  return[gg_lng,gg_lat]
  def wgs84_to_gcj02(lng,lat):
  """
  WGS84转GCJ02(火星坐标系)
  :param lng:WGS84坐标系的经度
  :param lat:WGS84坐标系的纬度
  :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[mglng,mglat]
  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 bd09_to_wgs84(bd_lon,bd_lat):
  lon,lat=bd09_to_gcj02(bd_lon,bd_lat)
  return gcj02_to_wgs84(lon,lat)
  def wgs84_to_bd09(lon,lat):
  lon,lat=wgs84_to_gcj02(lon,lat)
  return gcj02_to_bd09(lon,lat)
  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)

  到此为止,这篇文章就给大家介绍到这里了,希望可以给大家带来更多的帮助。