Разбор адресов на составляющие
Имеется список адресов, например:
Абрамцевская улица, дом 16 Б
ул. Абрамцевская, д.3
ул Абрамцевская 5
Абрамцевская ул., 5/2
Имеется так же класс:
class Address:
def __init__(self, type, type_house, number_house):
self.type = type # улица или шоссе
self.name = name # название улицы
self.type_house = 'дом'
self.number_house = number_house # все, что справа от названия улицы
Как разбить строки на составляющие поля класса Address? Пробую делать через split по знакам деление слов в строке, далее циклом перебираю получившийся список на поиск ключевых слов, таких, как ул, улица итд. потом ищу по ключевому слову дом, д. В зависимости от индекса элемента или его отсутствия нахожу название улицы. Как то очень все не уклюже получается, может у кого то есть варианты реализации более интересные
Ответы (1 шт):
Есть готовая библиотека Natasha для подобных задач (извлечения фактов из текста), но она довольно заметно изменилась с тех пор, как я с ней пробовал работать. Куда-то дели парсер адресов, приходится ставить старую версию, как рекомендуют в README:
API may change, for realworld tasks consider using low level libraries from Natasha project. Models optimized for news articles, quality on other domain may be lower. To use old
NamesExtractor,AddressExtactordowngradepip install natasha<1 yargy<0.13
У меня установилось в таком варианте команды (нужно взять в кавычки, т.к. знак < - оператор перенаправления ввода)
pip install "natasha<1" "yargy<0.13"
Примерный код:
from natasha import AddressExtractor
extractor = AddressExtractor()
addresses = """
Абрамцевская улица, дом 16 Б
ул. Абрамцевская, д.3
ул Абрамцевская 5
Абрамцевская ул., 5/2
""".strip().splitlines()
for address in addresses:
matches = extractor(address)
for match in matches:
print(match.fact)
Вывод:
Address(parts=[Street(name='Абрамцевская', type='улица'), Building(number='16 Б', type='дом')])
Address(parts=[Street(name='Абрамцевская', type='улица'), Building(number='3', type='дом')])
Address(parts=[Street(name='Абрамцевская', type='улица'), Building(number='5', type=None)])
Address(parts=[Street(name='Абрамцевская', type='улица'), Building(number='5/2', type=None)])
Дальше для заполнения вашего объекта нужно пройти по списку в поле parts извлеченного адреса, у каждого элемента проверить тип, прописать в соответствующее поле вашего объекта.
Если возникнут трудности с этим, я позже могу набросать пример, как это сделать.
UPD. Оказалось, что парсер адресов теперь называется AddrParser, но на ваших данных он не всегда находит номер дома, так что возможно имеет смысл использовать более старую версию. Пример кода (версия natasha == 1.4.0):
from natasha import AddrExtractor
import pymorphy2
morph = pymorphy2.MorphAnalyzer()
extractor = AddrExtractor(morph)
addresses = """
Абрамцевская улица, дом 16 Б
ул. Абрамцевская, д.3
ул Абрамцевская 5
Абрамцевская ул., 5/2
""".strip().splitlines()
for address in addresses:
matches = extractor(address)
print([match.fact for match in matches])
Вывод:
[AddrPart(value='Абрамцевская', type='улица'), AddrPart(value='16 Б', type='дом')]
[AddrPart(value='Абрамцевская', type='улица'), AddrPart(value='3', type='дом')]
[AddrPart(value='Абрамцевская', type='улица')]
[AddrPart(value='Абрамцевская', type='улица')]