python: geopy扩展包

289 阅读4分钟

0/参考网址

blog.csdn.net/weixin_4251… www.itdaan.com/blog/2018/0… cloud.tencent.com/developer/a… cloud.tencent.com/developer/a…

1/简介

这里介绍一个Python库包 Geopy,借助它也可以实现经纬度地理位置转换。
实现经纬度地理位置转换,其原理是借助了第三方API平台。
因为市面上可以提供经纬度转换的第三方平台很多(比如百度,谷歌,高德等),为了方便, Geopy把这些接口都分别封装在一个类中,借助Geopy模块来调用,支持的第三方台如下:
比如我们熟悉的有百度地图,谷歌地图等。

图片.png

2/geopy包的功能有哪些

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

<1>地理编码

地理编码: 就是传入地址的名字,得到它的经纬度。
比如你输入山东省济南市xxx小区西门,然后可以得到该地址的经纬度,这就是地理编码。

使用地理编码功能时,需要借助 geopy包 的 geocoders 模块(.py文件),geopy 把所有第三方API封装到 geocoders 中。
这里选用 OpenStreetMap 平台上提供的 Nominatim 地理编码器,因为可以免费供我们使用,不需要申请 API ,但缺点是限流,限额,不能大规模频繁访问,否则会返回 403,429错误代码。
from geopy.geocoders import Nominatim  # 导入geopy库包的geocoders.py模块中的Nominatim类
geolocator=Nominatim()  # 类的实例化对象

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

# 结果如下
# 西二旗北路, 东北旺村, 海淀区, 北京市, 102208, 中国
# 40.056793 116.305811

<2>逆地理编码

 逆地理编码,就是输入经纬度,得到地址的名字。
from geopy.geocoders import Nominatim
geolocator=Nominatim()
location= geolocator.reverse("40.056793 116.305811")
print(location.address)

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

图片.png

<3>计算2个点之间的距离

计算距离的函数,都是在distance.py模块中。
计算距离有两种:大圆距离与大地线距离(默认,更精确)。
    - 大圆算法将地球简化为一个圆球,其计算的距离是球面上过两点的大圆距离。
    - 大地线使用目前国际通用的方法,用旋转椭球面表示地球,其计算的是两点在椭球面上的最短距离。

普及一下:什么是大圆距离?
    大圆距离(英语:Great-circledistance)指的是从球面的一点A出发到达球面上另一点B,所经过的最短路径的长度。一般说来,球面上任意两点AB都可以与球心确定唯一的大圆,这个大圆被称为黎曼圆,而在大圆上连接这两点的较短的一条弧的长度就是大圆距离。若这两点和球心正好都在球的直径上,则过这三点可以有无数大圆,但两点之间的弧长都相等,且等于该大圆周长的一半,r是球的半径。由于地球类似球体,地球上任何两点沿球面的最短距离都可以通过大圆距离的公式估算的出,这在航空和航海上都有很大作用。
    
单位有英里miles,km,m.
geopy库包的distance模块中有很多计算2个点之间距离的函数,
比如distance.distance()函数,distance.great_circle()函数,

因为地球具体来说是椭圆,所以不能按照常规方法来计算 ,目前比较流行的几个模型有以下几个:

图片.png

根据官方介绍,官网选择的是 WGS-84 模型,根据统计最终计算到的距离误差最高在0.5%左右,误差很小。

<1>大圆距离distance.great_circle()

 使用的是distance.py模块中的great_circle()函数。
 优点:计算速度快
 缺点:不如大地线距离精确。
from geopy.distance import great_circle
newport_ri = (41.49008, -71.312796)     # 纬度在前
cleveland_oh = (41.499498, -81.695391)  # 纬度在前
print(great_circle(newport_ri, cleveland_oh).miles)  
# 这里是以英里为单位输出,其他的单位还有km,m
# 537.1485284062816

<2>大地线距离distance.distance()

大地线距离是默认的,更精确。
缺点:计算速度比大圆距离要慢。
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)

# 调用geopy库包中的distance.py模块中的distance()函数。
print(distance.distance(wellington, salamanca).km) # 以 km 作为单位输出
# output
# 19959.6792674

dist = distance.distance((45.768189, 126.6212835), (39.907359, 116.3912630)) 
#返回一个distance对象,其中包含单位转换方法 dist.kilometers #单位转换,获取km,m或者英里为单位的距离

<3>distance.geodesic()

这个函数我也不知道是什么距离。
该函数和distance.distance()大地线距离的结果是一模一样的。

<4>优缺点

大地线距离:
    优点:更加精确
    确定:计算速度慢

大圆距离:
    优点:计算速度快
    缺点:不如大地线距离精确。