Есть ли способ преобразовать местоположение Geopy в короткую строку адреса? - PullRequest
1 голос
/ 02 апреля 2020

У меня есть географическое местоположение, которое я хотел бы представить в виде строки.

Я пытался использовать str(location.address), но это дает слишком длинную строку, например 48, De Keyserlei, Statiekwartier, Antwerpen, Vlaanderen, 2018, België - Belgique - Belgien

После некоторых исследований в Интернете я нашел способ получить местоположение в качестве словаря, чтобы я мог создать свой собственный адрес, добавив значения этого словаря.

Тогда проблема в том, что, например, не все адреса имеют улицу, или у некоторых есть город вместо города, и есть намного больше исключений, слишком много, чтобы проверить все, есть ли в словаре.

Вот пример кода для проверки:

from geopy.geocoders import Nominatim

geolocator = Nominatim(user_agent="[PlaceHolder]")
location = geolocator.reverse("51.217497747238106, 4.418478198686335")
print(str(location.address))  # Way too long address


def location_str(location):
    addr_dict = location.raw["address"]
    location_str = addr_dict["road"] + " " \
                   + addr_dict["house_number"] + ", " \
                   + addr_dict["postcode"] + " " \
                   + addr_dict["city"]
    return location_str


print(location_str(location))  # Works as I want it to be

# Let's try a different address
location = geolocator.reverse("51.217497747238106, 4.418478198686335")
print(location_str(location))  # KeyError: 'road' (because the address doesn't have a road)

Итак, знаете ли вы способ представить это местоположение в виде короткой читаемой строки?

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Немного грубым способом обработки разных ключей, связанных с одним и тем же значением, вы можете расширить каждый словарь до фактически словаря много-к-одному.

Snce У меня нет geopy установлено, я не могу запустить ваш код, но, надеюсь, следующее достаточно близко, чтобы дать вам представление о том, что я предлагаю.

Обратите внимание, что по крайней мере один из ключей в каждой группе эквивалентов должен существует в адресной книге - в противном случае будет сгенерировано исключение.

geolocator = {
    "51.217497747238106, 4.418478198686335":
        dict(road='De Keyserlei', house_number='48', postcode='PC1234', city='Antwerpen'),
    "51.217497747238107, 4.418478198686335":
        dict(street='De Keyserlei', house_number='49', postcode='PC1235', town='Antwerpen'),
}

EQUIV_KEYS = [('city', 'town', 'village'),
              ('road', 'street', 'avenue'),]


def expand_keys(addr_dict, equiv_keys):
    res = addr_dict.copy()
    for group in equiv_keys:
        for key in group:
            if key in addr_dict:
                match = key
                break
        else:
            raise KeyError(f'None of the keys in group {group} exist')

        # Set the values of the other keys to the one that matched.
        for key in group:
            if key != match:
                res[key] = addr_dict[match]

    return res

def location_str(location):
    addr_dict = geolocator[location]
    equiv_dict = expand_keys(addr_dict, EQUIV_KEYS)

    location_str = (f'{equiv_dict["road"]} {equiv_dict["house_number"]}, '
                    f'{equiv_dict["postcode"]} {equiv_dict["city"]}')
    return location_str


location1 = "51.217497747238106, 4.418478198686335"
print(location_str(location1))

location2 = "51.217497747238107, 4.418478198686335"
print(location_str(location2))

0 голосов
/ 08 апреля 2020

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

from geopy.geocoders import Nominatim
from geopy.exc import GeocoderTimedOut

def get_from_dict(dictionary, *args):
    for word in args:
        if word in dictionary:
            return dictionary[word]
    return ""

def addr(lat, long):
    geolocator = Nominatim(user_agent="[PlaceHolder]")

    try:
        location = geolocator.reverse(str(lat) + ", " + str(long))
    except GeocoderTimedOut:
        return "Geocoder timed out :/"

    addr_dict = location.raw["address"]

    location_str = ""

    # Address line
    location_str += get_from_dict(addr_dict, "road", "avenue", "street", "cycleway", "pedestrian") + " "
    # Number
    location_str += get_from_dict(addr_dict, "house_number")
    # Only add a ", " if you've already added something so far (that's not a space)
    location_str += ", " if len(location) > 1 else ""
    # Postcode
    location_str += get_from_dict(addr_dict, "postcode") + " "
    # City
    location_str += get_from_dict(addr_dict, "city", "town")

    # When nothing could be added
    if len(location_str) <= 4:
        location_str = str(location.address)

    return location_str

print(addr(51.221225, 4.399826))
...