НАЙТИ почтовый адрес в США в тексте (желательно с использованием регулярного выражения Python)

Отказ от ответственности: я очень внимательно прочитал этот поток: Поиск уличного адреса в string — Python или Ruby и многие другие ресурсы.

У меня пока ничего не работает.

Более подробно вот то, что я ищу:

Правила смягчены, и я определенно не прошу идеального кода, охватывающего все случаи; всего несколько простых базовых с предположениями, что адрес должен быть в формате:

а) номер дома (1...N цифр);

b) Название улицы: одно или несколько слов с заглавной буквы;

b-2) (необязательно) было бы лучше, если бы перед ним стояла аббревиатура. «С.», «Н.», «Э.», «В.»

в) (опционально) блок/квартира/и т.д. может быть любое (в т.ч. пустое) количество произвольных символов

г) "тип" улицы: одна из ("ул.", "пр.", "проходная");

д) Название города: 1 или более слов с заглавной буквы;

f) (необязательно) аббревиатура штата (2 буквы)

g) (необязательно) почтовый индекс, состоящий из 5 любых цифр.

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

Я пробую такие выражения до сих пор:

pat = re.compile(r'\d{1,4}( \w+){1,5}, (.*), ( \w+){1,5}, (AZ|CA|CO|NH), [0-9]{5}(-[0-9]{4})?', re.IGNORECASE)

>>> pat.search("123 East Virginia avenue, unit 123, San Ramondo, CA, 94444")

Не работает, и мне не просто понять почему. В частности: как мне отделить в моем шаблоне группу любых слов от одного из конкретных слов, которые должны следовать, например, аббревиатура состояния. или уличный" тип ("ул., пр.)?

Во всяком случае: вот пример того, что я надеюсь получить: Учитывая def ex_addr(text): # магия повтора # возвращает 1-й адрес (все адреса?) или None, если ничего не найдено

for t in [
'The meeting will be held at 22 West Westin st., South Carolina, 12345 on Nov.-18',
'The meeting will be held at 22 West Westin street, SC, 12345 on Nov.-18',

'Hi there,\n How about meeting tomorr. @10am-sh in Chadds @ 123 S. Vancouver ave. in Ottawa? \nThanks!!!',
'Hi there,\n How about meeting tomorr. @10am-sh in Chadds @ 123 S. Vancouver avenue in Ottawa? \nThanks!!!',

'This was written in 1999 in Montreal',

"Cool cafe at 420 Funny Lane, Cupertino CA is way too cool",

"We're at a party at 12321 Mammoth Lane, Lexington MA 77777; Come have a beer!"
] print ex_addr(t)

Я хотел бы получить:

'22 West Westin st., South Carolina, 12345'
'22 West Westin street, SC, 12345'
'123 S. Vancouver ave. in Ottawa'
'123 S. Vancouver avenue in Ottawa'
None # for 'This was written in 1999 in Montreal',
"420 Funny Lane, Cupertino CA",
"12321 Mammoth Lane, Lexington MA 77777"

Не могли бы вы помочь?


person bzdjamboo    schedule 21.08.2013    source источник
comment
взгляните на PLY, возможно, что-то подобное ... Я сомневаюсь, что регулярное выражение будет достаточно хорошим   -  person Joran Beasley    schedule 22.08.2013
comment
Спасибо, Джоран, мне нужно подумать о PLY. Кажется, это еще более крутая кривая, чем создание правил для nltk.ne_chunk, но кто знает :-). Спасибо в любом случае! Кстати: почему именно регулярное выражение было бы недостаточно хорошим? Мне не нужно более 90% воспоминаний.....   -  person bzdjamboo    schedule 23.08.2013


Ответы (2)


\d{1,4}( \w+){1,5}, (.*), ( \w+){1,5}, (AZ|CA|CO|NH), [0-9]{5}(-[0-9]{4})?

В этом регулярном выражении у вас слишком много пробелов (перед ( \w+){1,5}, которое уже начинается с единицы). Удалив его, он соответствует вашему примеру.

Я не думаю, что вы можете предположить, что там будет «блок 123» или что-то подобное, или их может быть несколько (например, «корпус А, кв. 3»). Обратите внимание, что в исходном регулярном выражении . может соответствовать ,, что может привести к очень длинным (и нежелательным) совпадениям. Вероятно, вам следует принять несколько таких групп с ограничением по количеству (например, заменить , (.*) на что-то вроде (, [^,]{1,20}){0,5}.

В любом случае, вы, вероятно, никогда не получите что-то на 100% точное, что примет любые вариации, которые могут предложить люди. Сделайте много тестов! Удачи.

person remram    schedule 21.08.2013
comment
Спасибо @ремрам! Я только изучаю регулярное выражение.... :-). Вот как выглядит мой текущий: есть комментарии? - >>> pat = re.compile(r'\d{1,7}( \w+){1,6} (st|street|ave|avenue|ln|lane), (apt|unit|apartment)[\., ]+.*[\. ,]+(AZ|CA|CO|NH)[\. ,]\d{5}') - person bzdjamboo; 23.08.2013
comment
Я не уверен, для чего предназначена часть [\., ]+, и будьте осторожны, так как часть .* потенциально может занять много текста. - person remram; 23.08.2013

Я только что наткнулся на это в GitHub, так как у меня похожая проблема. По-видимому, работает и является более надежным, чем ваше текущее решение.

https://github.com/madisonmay/CommonRegex

Глядя на код, регулярное выражение для уличного адреса учитывает гораздо больше сценариев. '\d{1,4} [\w\s]{1,20}(?:улица|st|проспект|авеню|дорога|rd|шоссе|шоссе|площадь|площадь|тропа|trl|проезд|dr| суд|ct|бульвар|pkwy|круг|cir|бульвар|бульвар)\W?(?=\s|$)'

person ccdpowell    schedule 15.01.2015