使用 geopy 处理地址和坐标数据
你一定知道地物的地址与其大地坐标之间存在对应关系。以往当我需要某个城市或标志物的坐标时,都是通过电子地图服务或者维基百科查询,这样的效率很低。geopy 是 Python 处理地理数据的包,它封装了大量的公共地图服务,用它来处理地址与坐标的关系非常方便。同时,其距离计算功能也比较强大。
本文将对 geopy 的主要功能进行介绍。
安装
geopy 项目基于 MIT 协议开源,代码托管在 Github 上。当前的 geopy 支持 Python 2.7 以及 Python 3.4 以上的版本。但根据开发计划,即将发布的 geopy 2.0 将只支持 Python 3。你可以使用 pip 来方便地安装 geopy:
1 | pip install geopy |
地址与坐标计算
geopy 支持众多的电子地图服务,例如著名的 Google、Bing、百度、Here 等,你可以通过如下的代码查询其支持的所有服务商:
1 | import geopy |
这些服务商被封装为对应的类,并且提供统一的方法供使用者调用。例如下面提到的地址和坐标查询的 geocode
和 reverse
函数。
地址查询
使用 geopy 查询地址前需要首先选择一个地图服务,绝大多数的服务需要一个密钥(api_key)。你需要到其开发者页面注册和申请,例如百度。免费的密钥通常会对使用频率和次数做限制。出于演示目的,我们以不需要密钥的 OpenStreetMap 服务作为例子:
1 | from geopy.geocoders import Nominatim |
这里的 Nominatim
类为对 OpenStreetMap 服务的实现和封装。其提供的 geocode
方法用于将关键字在地图上查询,并返回一个 Location
对象。你可以用如下的方式获取结果:
1 | location.address |
坐标查询
同样的,你可以通过 reverse
方法输入坐标来查询地址:
1 | '45.768189, 126.6212835') location = geolocater.reverse( |
reverse
方法接收经纬度字符串作为输入,纬度在前,经度在后。该方法同样返回一个 Location
对象。
距离计算
geopy 的距离计算功能包含在 distance
中。其计算的距离有两种:大圆距离与大地线距离。其区别在于:
- 大圆算法将地球简化为一个圆球,其计算的距离是球面上过两点的大圆距离;
- 大地线使用目前国际通用的方法,用旋转椭球面表示地球,其计算的是两点在椭球面上的最短距离。
如果你对地球物理学有过了解,一定知道大地线算法更精确。实际上,geopy 默认的距离计算方法就是大地线。你可以通过如下方式计算哈尔滨到北京的大地线距离:
1 | from geopy import distance |
该方法返回一个 Distance
对象,其中包含单位转换方法,方便获取以千米、米或者英里为单位的距离。你也可以用等效的显式方法:
1 | 45.768189, 126.6212835), (39.907359, 116.3912630)) dist = distance.geodesic(( |
但大地线的劣势在于计算速度太慢,如果你可以容忍一定的误差(0.5% 以内),完全可以采用大圆算法替代。根据我的测试,大圆距离计算时间大约只有前者的 1/20。大圆距离的使用方式如下:
1 | 45.768189, 126.6212835), (39.907359, 116.3912630)) gc = distance.great_circle(( |
该方法同样返回 Distance
对象,并且可以看到,哈尔滨到北京的大圆与大地线距离之间有 0.13% 的差异。