基于Python 实现地理位置和经纬度坐标如何转换

做地图可视化时需要提供经纬度坐标,但一般来说我们手上拿到的通常只有地理位置,比如说 北京市东大街302号狗不理包子店,可视化之前需要经纬度坐标转换

需要转换的坐标如果仅有几个还好,可以直接借助谷歌地图自带的经纬度转换,但真实场景下需要转换的数据量可能要上百甚至上千,再手动的话就比较头疼了

如何将地理位置批量转化为经纬度坐标? 本文将针对这个问题,介绍两个用 Python 来实现的方法

1,调用第三方 API

最常见办法就是调用第三方 API,例如百度、高德地图等服务平台,提供了相应的功能接口,它们的这类技术已经非常成熟啦,准确稳定,关键还是免费的 ~,本期教程以百度为例(高德的用方类似),介绍一下其用法

1.1,用百度账号登陆百度地图控制台

百度地图开放平台

image-20210417142947516

1.2,创建一个应用,获取 AK 参数

登录控制台之后,选择左侧 应用管理-> 我的应用 -> 创建应用

image-20210417143233823

创建应用页面中有三项信息需要填写

  • 应用名称,无限制随意填写即可;
  • 应用类型 ,选择服务端
  • IP 白名单,只是个人简单测试的话0.0.0.0/0 即可,如果考虑安全问题, 可以将自己的 IP 填进去, AK 参数泄露的话非本机 IP 无法访问,这样也不用担心额度被其他用户盗用
image-20210417150550228

1.3,地理编码、逆地理编码

经纬度地理位置根据转换方向分为两类,接下来我们分别演示一下其用法:

  • 地理编码: 将地理地址转换为坐标点(经纬度);
  • 逆地理编码,将经纬度转化为地理地址;

1.3.1 地理编码

下面就是 Python 测试代码块,将 AK 参数(前面申请到的)和你需要转换的地理位置拼接到 官方提供的 url 中,用 requests 访问即可,

import requests
import json
import re

AK = '你的AK'
address ='北京市海淀区上地十街10号'
url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}&callback=showLocation'.format(address,AK)
res = requests.get(url)

print(res.text)
results = json.loads(re.findall(r'\((.*?)\)',res.text)[0])

print('\n')
print('location is ',results['result']['location'])

输出结果如下

showLocation&&showLocation({"status":0,"result":{"location":{"lng":116.3084202915042,"lat":40.05703033345938},"precise":1,"confidence":80,"comprehension":100,"level":"门址"}})


location is  {'lng': 116.3084202915042, 'lat': 40.05703033345938}

1.3.2 逆地理编码

逆地理编与地理编码用法相似

lat = '40.05703033345938'
lng = '116.3084202915042'
AK = '你的AK'


url = 'http://api.map.baidu.com/reverse_geocoding/v3/?ak={}&output=json&coordtype=wgs84ll&location={},{}'.format(AK,lat,lng)

res = requests.get(url)

print(res.text)
address = json.loads(res.text)['result']['formatted_address']

print('\n')
print('address is ',address)

像我们这类免(bai) 费 piao) 用户,借助百度 API 每天最高可调用 6000 次,这个量级基本上能满足我们日常需要,但如果这个数量满足不了你的话,可以在线购买更高的使用额度

image-20210417151134728

2,Geopy

2.1 Geopy 库介绍

这里介绍一个Python 包 Geopy ,借助它也可以实现经纬度地理位置转换,

这款包之经纬度转换原理其实还是借助了第三方 API 平台,因为市面上提供经纬度转换 第三方平台很多,为了方便, Geopy 把这些接口都分别封装在一个类中,借助 Geopy 模块来调用,支持的第三放平台如下

image-20210417161926347

Geopy作为一个专注于地理处理包之外, 除了能实现上面地理编码逆地理编码功能之外,还有一个其它令我经验的功能, 提供两个经纬度坐标,计算他们在地球上的最短距离

下面将介绍一下 Geopy 的具体用法,

2. 2 地理编码

使用 地理编码功能时,需要借助 Geopy 的 geocoders 模块,Geopy 把所有第三方API封装到 geocoders 中

image-20210417164945976

这里选用 OpenStreetMap 平台上提供的 Nominatim 地理编码器,因为可以免费供我们使用,不需要申请 API ,但缺点是限流,限额,不能大规模频繁访问,否则会返回 403,429错误代码

from geopy.geocoders import Nominatim
geolocator=Nominatim()
location= geolocator.geocode("北京市海淀区西二旗北路")
print(location.address)
print(location.latitude,location.longitude)

结果如下

西二旗北路, 东北旺村, 海淀区, 北京市, 102208, 中国
40.056793 116.305811

2.3 逆地理编码

from geopy.geocoders import Nominatim
geolocator=Nominatim()
location= geolocator.reverse("40.056793 116.305811")
print(location.address)

结果如下

1#, 西二旗北路, 东北旺村, 海淀区, 北京市, 102208, 中国

结果看起来还不错,简单方便;但提醒一下,因为前面说过 Nominatim 模块是限额度的,不要频繁访问,否则会出现以下错误

image-20210417175101978

2.4 根据经纬度计算距离

Geopy 最让我惊喜的是这个用法,提供两个经纬度坐标计算他们之间的距离,因为地球具体来说是椭圆,所以不能按照常规方法来计算 ,目前现有比较流行的几个模型有以下几个

              model             major (km)   minor (km)     flattening
ELLIPSOIDS = {'WGS-84':        (6378.137,    6356.7523142,  1 / 298.257223563),
              'GRS-80':        (6378.137,    6356.7523141,  1 / 298.257222101),
              'Airy (1830)':   (6377.563396, 6356.256909,   1 / 299.3249646),
              'Intl 1924':     (6378.388,    6356.911946,   1 / 297.0),
              'Clarke (1880)': (6378.249145, 6356.51486955, 1 / 293.465),
              'GRS-67':        (6378.1600,   6356.774719,   1 / 298.25),
              }

根据官方介绍,官网选择的是 WGS-84 模型,根据统计最终计算到的距离误差最高在0.5%左右;使用方法如下

from geopy import distance
newport_ri = (41.49008, -71.312796)
cleveland_oh = (41.499498, -81.695391)
print(distance.distance(newport_ri, cleveland_oh).miles)#最后以英里单位输出

#output
538.39044536

wellington = (-41.32, 174.81)
salamanca = (40.96, -5.50)
print(distance.distance(wellington, salamanca).km)# 以 km 作为单位输出
19959.6792674

3 批量地址坐标转换

上面聊了这么多知识点,下面引入一个案例来简单回顾一下;本案例中借助百度API 来实现地理位置坐标转换,把一个 csv 表格内的所有地址位置数据批量转换为经纬度

3.1 数据读取

import pandas as pd
import string
data_path = 'H:/Data/Latlon/map-location.csv'
df = pd.read_csv(data_path,encoding='GB18030')
df

一共有 98 条数据,每条数据都表示一个地理位置;数据明显有一些扰乱项,例如左端的数字字符、以及数据中的分隔符\t;因此转换之前需要对数据进行一次预处理操作

image-20210417213923485

3.2 数据预处理

def process_str(x):
    # 数据预处理,去掉前面的数字、及字符串中 \t
    x = str(x).replace('\t','')
    x = str(x).strip(string.digits)
    return x 
df['location']  = df['location'].apply(process_str)
df

预处理结果如下

image-20210417214443969

3.3 地理编码(经纬度转换)

import time
start = time.time()
AK = '你的AK'
def get_location(str1):
    # 获取经纬度坐标
    url = 'http://api.map.baidu.com/geocoding/v3/?address={}&output=json&ak={}&callback=showLocation'.format(str1,AK)
    res = requests.get(url)
    results = json.loads(re.findall(r'\((.*?)\)',res.text)[0])
    return (results['result']['location']['lat'],results['result']['location']['lng'])
df['(lat,lng)'] = df['location'].apply(get_location)
print('耗时 {}s'.format(time.time()-start))
print(df)

为了测试转换效率,这里我加了一个计时器;98 条数据成功转换后共耗时 4.65s 左右,效率还不错,要比 Geopy 优秀得多,

image-20210417214833306

3.5 案例源码数据

我已经把本案例中用到代码的数据打包再一起了,感兴趣的可以在公号 程序员大飞 后台回复关键字:210418 ,即可获取!

4. 小结

上面介绍了这么多,最后做个小结;聊一下这两种方法在 地理坐标转换方面 各自的优势和劣势

  • 第三方API
    • 优势:地理编码、逆编码比较准确,精度高;且支持高并发;
    • 劣势:不支持国外,环境配置较为复杂;
  • Geopy (用 Nominatim 模块的话)
    • 优势:简单方便,上手快;支持国外地理编码
    • 劣势:不支持并发访问、效率低且精度较低;

这里给大家一个建议,如果地址数据在国内的话 经纬度转换 建议用第三方 API,稳定且准确;若是涉及下纬度距离计算、单位换算或地址数据在国外,建议用 Geopy

好了,以上就是本篇文章的全部内容啦,如果对你有所帮助,点个赞是对我最大的鼓励

最后感谢大家的阅读,我们下期见~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 193,968评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,682评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,254评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,074评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,964评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,055评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,484评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,170评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,433评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,512评论 2 308
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,296评论 1 325
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,184评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,545评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,150评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,437评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,630评论 2 335

推荐阅读更多精彩内容