Как получить геолокацию в Python

Как получить геолокацию в Python


Улучшите свои навыки программирования с помощью объяснителя кода на базе искусственного интеллекта. Получайте информацию, как никогда раньше!

Геокодирование - это процесс преобразования описания местоположения (такого как физический адрес или название места) в пару широты и долготы на поверхности Земли для этого места.

Это также относится к преобразованию географических координат в описание местоположения (например, адрес); это часто называют обратным геокодированием. В этом руководстве мы узнаем, как сделать и то, и другое с помощью библиотеки GeoPy в Python.

Однако, если вы хотите геолокировать IP-адреса, то этот учебник для вас.

GeoPy - это клиент Python, который предоставляет несколько популярных веб-сервисов геокодирования; это позволяет разработчикам Python легко находить координаты адреса, города или страны, и наоборот.

Для начала давайте установим его:

pip3 install geopy

Копировать

GeoPy предоставляет множество оболочек сервисов геокодирования, таких как OpenStreetMap NominatimGoogle Geocoding API V3, Bing Maps и другие. В этом руководстве мы будем придерживаться OpenStreetMap Nominatim.

Вот что мы рассмотрим:

Получение широты и долготы из адреса (геокодирование)

В этом разделе мы будем использовать OpenStreetMap Nominatim API для получения широты и долготы из физического адреса, города или любого названия местоположения.

Давайте сначала импортируем библиотеку:

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

Копировать

Обратите внимание, что мы выбрали Nominatim geocoder, теперь создаем его новый экземпляр:

# 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 атрибуте.

Как вы можете видеть, API Nominatim не требует полного адреса (который состоит из улицы, номера дома и города), вы также можете передавать адреса компаний и точки ваших интересов, он поддерживает это!

Однако, если вы вызываете эту функцию повторно (например, перебираете список адресов), вы столкнетесь с ошибкой тайм-аута, и это потому, что, если вы прочитали Политику использования 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(), который принимает координаты (latitude и longitude) в виде строки, разделенной запятой.

Следующая функция изменяет координаты на противоположные, соблюдая политику использования 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}

Копировать

Таким образом, это вернет все адресные данные, включая штат, город, почтовый индекс, районы и многое другое. Если вы хотите вернуть эту информацию на определенном языке, вы можете установить для language параметра значение желаемого языка, или вы можете установить для него значение False языка по умолчанию для этого конкретного местоположения.

Заключение

Как всегда, мы увидели только простые примеры того, что может делать GeoPy; я настоятельно рекомендую вам прочитать документацию, если вас интересуют более продвинутые утилиты.

Узнайте также: Как получить информацию о доменном имени на Python.

Счастливого кодирования ♥

Понравилась статья? Вам понравится наш конвертер кодов еще больше! Это ваше секретное оружие для легкого программирования. Попробуйте!

 Просмотреть полный код 

Код для Как получить геолокацию в Python Учебное пособие

geolocator.py

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

# 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)


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)

Копировать

reverse_geolocator.py

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

app = Nominatim(user_agent="tutorial")

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)




Report Page