Python如何获取地理位置,可以用Geopy这个库

已收录   阅读次数: 690
2022-02-0222:22:54 发表评论
摘要

好久没有学习Python编程相关内容了,今天刚好有兴趣学习一番,本篇文章就来介绍如何用开源的GeoPy这个依赖库来获取地理位置啦……

分享至:
Python如何获取地理位置,可以用Geopy这个库

开篇寄语

好久没有学习Python编程相关内容了,今天刚好有兴趣学习一番,本篇文章就来介绍如何用开源的GeoPy这个依赖库来获取地理位置啦。

内容详情

地理编码是将位置描述(例如物理地址或地点名称)转换为地球表面上该地点的一对纬度和经度的过程。

它还指将地理坐标转换为位置的描述(例如地址),这通常称为反向地理编码。在本教程中,我们将学习如何在 Python 中的 GeoPy 库的帮助下做到这两点。

GeoPy 是一个 Python 依赖库,提供多种流行的地理编码 Web 服务,它使 Python 开发人员可以轻松定位地址、城市或国家/地区的坐标,反之亦然。

首先,让我们安装它:

pip3 install geopy

GeoPy 提供了许多地理编码服务包装器,例如 OpenStreetMap Nominatim、Google Geocoding API V3、Bing Maps 等等。在本教程中,我们将坚持使用 OpenStreetMap Nominatim。

从地址获取纬度和经度(地理编码)

在本节中,我们将使用 OpenStreetMap Nominatim API 从物理地址、城市或任何位置名称获取纬度和经度。

from geopy.geocoders import Nominatim
import time
from pprint import pprint

请注意,我们选择了 Nominatim 地理编码器,现在创建它的一个新实例:

# instantiate a new Nominatim client
app = Nominatim(user_agent="tutorial")

现在让我们尝试从一个地址获取地理数据:

# get location raw data
location = app.geocode("Nairobi, Kenya").raw
# print raw data
pprint(location)

输出:

{'boundingbox': ['-1.444471', '-1.163332', '36.6509378', '37.1038871'],
 'class': 'place',
 'display_name': 'Nairobi, Kenya',
 'icon': 'https://nominatim.openstreetmap.org/images/mapicons/poi_place_city.p.20.png',
 'importance': 0.845026759433763,
 'lat': '-1.2832533',
 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. '
            'https://osm.org/copyright',
 'lon': '36.8172449',
 'osm_id': 9185096,
 'osm_type': 'relation',
 'place_id': 273942566,
 'type': 'city'}

太棒了,我们在 lat 属性中有纬度(我们可以通过 location['lat'] 访问)和在 lon 属性中的经度,我们还可以在 boundingbox 属性中访问地址的边界框。

但是,如果你重复调用这个函数(比如遍历一个地址列表),你会遇到一个超时错误,这是因为如果你阅读 Nominatim 使用策略,它要求你每秒最多使用 1 个请求,这是完全可以接受的,因为它是一项免费服务。

因此,以下函数在发出请求之前休眠一秒钟:

def get_location_by_address(address):
    """This function returns a location as raw from an address
    will repeat until success"""
    time.sleep(1)
    try:
        return app.geocode(address).raw
    except:
        return get_location_by_address(address)

因此,无论何时引发超时错误,我们都会捕获并递归调用该函数,该函数将再休眠一秒钟,并希望检索结果:

address = "Makai Road, Masaki, Dar es Salaam, Tanzania"
location = get_location_by_address(address)
latitude = location["lat"]
longitude = location["lon"]
print(f"{latitude}, {longitude}")
# print all returned data
pprint(location)

输出:

-6.7460493, 39.2750804
{'boundingbox': ['-6.7467061', '-6.7454602', '39.2741806', '39.2760514'],
 'class': 'highway',
 'display_name': 'Makai Road, Masaki, Msasani, Dar es-Salaam, Dar es Salaam, '
                 'Coastal Zone, 2585, Tanzania',
 'importance': 0.82,
 'lat': '-6.7460493',
 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. '
            'https://osm.org/copyright',
 'lon': '39.2750804',
 'osm_id': 23347726,
 'osm_type': 'way',
 'place_id': 89652779,
 'type': 'residential'}

从纬度和经度获取地址(反向地理编码)

现在要仅从纬度和经度检索地址、城市和国家以及各种其他信息,我们只需使用 reverse() 方法而不是 geocode(),它接受坐标(纬度和经度)作为用逗号分隔的字符串。

以下函数对坐标进行反向地理编码并遵守 Nominatim 使用策略:

def get_address_by_location(latitude, longitude, language="en"):
    """This function returns an address as raw from a location
    will repeat until success"""
    # build coordinates string to pass to reverse() function
    coordinates = f"{latitude}, {longitude}"
    # sleep for a second to respect Usage Policy
    time.sleep(1)
    try:
        return app.reverse(coordinates, language=language).raw
    except:
        return get_address_by_location(latitude, longitude)

所以这个函数需要纬度和经度作为参数并返回原始地理数据,这里是一个示例用法:

# define your coordinates
latitude = 36.723
longitude = 3.188
# get the address info
address = get_address_by_location(latitude, longitude)
# print all returned data
pprint(address)

输出:

{'address': {'country': 'Algeria',
             'country_code': 'dz',
             'county': 'Dar El Beida District',
             'postcode': '16110',
             'state': 'Algiers',
             'town': 'Bab Ezzouar'},
 'boundingbox': ['36.7231765', '36.7242661', '3.1866439', '3.1903998'],
 'display_name': 'Bab Ezzouar, Dar El Beida District, Algiers, 16110, Algeria',
 'lat': '36.72380363740118',
 'licence': 'Data © OpenStreetMap contributors, ODbL 1.0. '
            'https://osm.org/copyright',
 'lon': '3.188236679492425',
 'osm_id': 42812185,
 'osm_type': 'way',
 'place_id': 98075368}

所以这将返回所有地址数据,包括州、城镇、邮政编码、地区等。如果您希望以特定语言返回这些信息,您可以将语言参数设置为您想要的语言,或者您可以将其设置为 False 以获得该特定位置的默认语言。

总结

与往常一样,我们只看到了 GeoPy 可以做什么的简单示例,如果您对更高级的实用程序感兴趣,我强烈建议您阅读其文档。

  • 我的微信
  • 微信扫一扫加好友
  • weinxin
  • 我的微信公众号
  • 扫描关注公众号
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: