专栏名称: 城长数据
ArcGIS for Urabn planning.主要面向城市规划专业,通过全方位的ArcGIS技术与方法讲解,达到高效运用ArcGIS ,以辅助城市规划设计及研究的目的。
目录
相关文章推荐
HRTechChina  ·  突发:Workday宣布裁员1,750人,优 ... ·  2 天前  
中国人力资源  ·  明确了!二次合同后公司不续签是否要赔2N?人 ... ·  3 天前  
人力资源管理  ·  这款护手霜居然这么好用?感觉手年轻了十岁! ·  3 天前  
51好读  ›  专栏  ›  城长数据

如何使用百度Geocoding API进行地址解析,并进行坐标转换?

城长数据  · 公众号  ·  · 2017-03-21 07:28

正文

前段时间,由于项目需要,希望获得给定地址的经纬度坐标,以便后续进行空间分析。比如图1,希望获得各企业的经纬度坐标,如果是单个企业或者很少的企业,我们可以使用百度的坐标拾取系统人工查询(图2)。但是,如果有成千上万个企业,人工查询的方式显然是无法接受的。这时候,我们就需要借助百度Geocoding API来进行地址解析(图3)。最后,获得的百度经纬度坐标,我们还需要转换为国测局经纬度坐标以及WGS84经纬度坐标。下面,大家就随我一起学习如何使用百度Geocoding API进行地址解析,并进行坐标转换吧!

图1  企业列表

图2  百度坐标拾取系统

图3  百度Geocoding API



一、如何使用百度Geocoding API进行地址解析?


我们仍然采用Python来进行代码编写,先上代码(图4)。

图4  Geocoding API进行地址解析

1、导入需要的几个库,包括pandas、requests、re、time。

2、定义需要读取的Excel文件和需要导出的Excel文件。

3、使用pandas里面的read_excel函数读取文件并将读取的数据命名为data变量,并新建两列,包括经度与纬度。

4、通过for循环去生成请求的url地址,并获取请求返回的数据。由于返回的数据不是JSON数据,所以我们使用正则去获取经纬度坐标。其正则写法见第24行。

返回的数据示例:

showLocation&&showLocation({"status":0,"result":{"location":{"lng":116.30815063007148,"lat":40.056890127931279},"precise":1,"confidence":80,"level":"道路"}})

5、存储获取的经纬度数字。

需要说明的是,为了避免百度数据库中无该企业记录而无法获取经纬度数据,以及避免网页解析出现问题,我们需要加入try—except进行错误异常处理。

6、将生成的数据导出为excel文件(图5)。

图5  成功获取的坐标(约2W条记录,数据量还是比较大的)



二、如何将百度经纬度坐标转换为国测局、WGS84坐标?


1、编写坐标转换的代码(trans.py)。该代码为某网友编写,经测试可用。由于时间比较久了,我无法找到原出处,如果作者看到我的这篇文章,需要我进行署名,可联系我。

# -*- coding: utf-8 -*-

import json

import requests

import math


key = 'your key here'  # 这里填写api的key

x_pi = 3.14159265358979324 * 3000.0 / 180.0

pi = 3.1415926535897932384626  # π

a = 6378245.0  # 长半轴

ee = 0.00669342162296594323  # 扁率


def geocode(address):

"""

利用百度geocoding服务解析地址获取位置坐标

:param address:需要解析的地址

:return:

"""

geocoding = {'s': 'rsv3',

'key': key,

'city': '全国',

'address': address}

res = requests.get(

"http://restapi.amap.com/v3/geocode/geo", params=geocoding)

if res.status_code == 200:

json = res.json()

status = json.get('status')

count = json.get('count')

if status == '1' and int(count) >= 1:

geocodes = json.get('geocodes')[0]

lng = float(geocodes.get('location').split(',')[0])

lat = float(geocodes.get('location').split(',')[1])

return [lng, lat]

else:

return None

else:

return None


def gcj02tobd09(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 bd09togcj02(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 wgs84togcj02(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 gcj02towgs84(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):







请到「今天看啥」查看全文