Регулярное выражение для сопоставления адреса с подшаблонами

1

Я пытаюсь создать регулярное выражение для разбора адреса на пять частей: адрес1, который является адресом улицы, адресом2, который является номером квартиры или каким-либо другим, отображаемым в строке 2 адреса, города, штата и почтового индекса код.

Когда я запускаю это, python (или Django) re.search ошибку, которая указывает "неожиданный конец шаблона" при запуске re.search. Может ли кто-нибудь сказать мне, как изменить это регулярное выражение для правильного соответствия?

Я очень регулярное выражение noob. Я могу разглядеть большую часть того, что должен сделать этот, но я никогда бы не написал его сам. Я получил это от http://regexlib.com/REDetails.aspx?regexp_id=472.

re.compile(r"""
(?x)^(?n:
(?<address1>
    (\d{1,5}(\ 1\/[234])?(\x20[A-Z]([a-z])+)+ )
    | (P.O. Box \d{1,5}))\s{1,2}
(?<city>
    [A-Z]([a-z]) 
        + (\.?)(\x20[A-Z]([a-z])+){0, 2})\, \x20
(?<state>
    A[LKSZRAP] | C[AOT] | D[EC] | F[LM] | G[AU] | HI
    | I[ADL N] | K[SY] | LA | M[ADEHINOPST] | N[CDEHJMVY]
    | O[HKR] | P[ARW] | RI | S[CD] | T[NX] | UT | V[AIT] 
    | W[AIVY] 
    | [A-Z]([a-z])
        + (\.?)(\x20[A-Z]([a-z])+){0,2})\x20
(?<zipcode>
    (?!0{5})\d{5}(-\d {4})?)
)$"
""", re.VERBOSE)

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

PS Я знаю, что это пахнет домашней работой, но на самом деле это работает.

Изменение: запрашивался фактический код, поэтому он есть. Я оставил его, потому что все здесь на самом деле уже там, но, возможно, это поможет.

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

def parseAddress(address):
  pattern = r"^(?n:(?<address1>(\d{1,5}(\ 1\/[234])?(\x20[A-Z]([a-z])+)+ )|(P\.O\.\ Box\ \d{1,5}))\s{1,2}(?i:(?<address2>(((APT|APARTMENT|BLDG|BUILDING|DEPT|DEPARTMENT|FL|FLOOR|HNGR|HANGER|LOT|PIER|RM|ROOM|S(LIP|PC|T(E|OP))|TRLR|TRAILER|UNIT)\x20\w{1,5})|(BSMT|BASEMENT|FRNT|FRONT|LBBY|LOBBY|LOWR|LOWER|OFC|OFFICE|PH|REAR|SIDE|UPPR|UPPER)\.?)\s{1,2})?)(?<city>[A-Z]([a-z])+(\.?)(\x20[A-Z]([a-z])+){0,2})\, \x20(?<state>A[LKSZRAP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADL N]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD] |T[NX]|UT|V[AIT]|W[AIVY]|[A-Z]([a-z])+(\.?)(\x20[A-Z]([a-z])+){0,2})\x20(?<zipcode>(?!0{5})\d{5}(-\d {4})?))$"
  match = re.search(pattern, address)

Я использовал свой домашний адрес в качестве входных данных, но я попробовал "123 Main St., Austin, TX 12345" в качестве входных данных с тем же результатом.

  • 0
    да, вы можете использовать шаблон подробного регулярного выражения ( docs.python.org/py3k/howto/regex.html#regex-howto, а внизу вы найдете re.VERBOSE) также: можете ли вы дать точный пример кода, чтобы люди могли попробовать воспроизвести ошибку, которую вы получаете?
  • 0
    Открывающая кавычка должна иметь перед собой r чтобы сделать ее «необработанной строкой», где обратные косые черты не имеют особого значения.
Показать ещё 4 комментария
Теги:

5 ответов

4
Лучший ответ

Некоторые люди, возможно, не считают это ответом, но медведь со мной на минуту.

Я настоятельно рекомендую ПРОТИВ пытаться разобрать уличные адреса с помощью регулярного выражения. Уличные адреса не являются "правильными" в любом смысле этого слова. Существует бесконечная вариация, и если вы не ограничиваете себя очень ограниченной грамматикой, всегда будут строки, которые вы не можете проанализировать. Огромное количество времени и денег было вложено в решения для анализа адресов, начиная с Почтового офиса США и многих многих поставщиков услуг по очистке списка. Просто Google "разглашает уличные адреса", чтобы получить намек на объем проблемы. Существуют коммерческие решения и некоторые бесплатные решения, но комментарии в Интернете показывают, что никто не делает это правильно все время.

Я также говорю по опыту. В 80-е годы я работал в компании по набору данных, и нам приходилось разбирать адреса. Мы никогда не смогли разработать решение, которое отлично работало, и для данных, которые мы захватили (у нас был большой отдел клавиатуры), мы разработали специальный синтаксис примечаний, чтобы операторы могли вставлять разделители в соответствующие местоположения, чтобы помочь разбору.

Посмотрите на некоторые бесплатные услуги там. Вы сэкономите много хлопот.

  • 0
    хаха, да, это самое быстрое решение;)
2

Установите флаг x (verbose) в регулярное выражение, то есть: (?x)

  • 0
    Вы предлагаете r"^(?x:(?<address1>... вместо "^(?n:(?<address1> ? Я изменил и вопрос, и мой код с r перед открывающей цитатой.
  • 0
    @Caleb, (?r)^(?n:(?<add...
Показать ещё 3 комментария
1

ответ без регулярного выражения: проверьте usaddress библиотеки python (там также есть веб-интерфейс для проверки)

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

0

Джим Гаррисон (см. Выше) корректен - адреса слишком разнообразны для синтаксического анализа с регулярным выражением. Я работаю в компании по проверке адреса - SmartyStreets. Попробуйте наш API LiveAddress - конечная точка REST предоставляет все компоненты адреса, проанализированные в приятном, легком в использовании ответе JSON. Здесь образец:

https://github.com/smartystreets/LiveAddressSamples/blob/master/python/street-address.py

  • 0
    Разве это не предполагает, что у меня уже есть адрес, разобранный на улицу, город, почтовый индекс и т. Д.?
  • 0
    Хороший вопрос. Текущая версия API поддерживает создание кода города, штата и почтового индекса в параметрах city или lastline. Таким образом, если вы можете разделить адрес на две части (уличный адрес и все остальное), вы можете использовать API для дальнейшего его анализа. Сложнее всего с этим (очевидно) определить, где заканчивается адрес улицы и начинается последняя строка информации. У нас есть планы для дополнительного поля ввода, в котором может быть указан весь адрес, но эта функция должна содержать огромное количество отклонений в адресных данных. Оставайтесь с нами (blog.smartystreets.com) ...
0

Ваше регулярное выражение терпит неудачу с первым символом n, который вы можете проверить следующим образом. Создайте файл test.py и поставьте следующее:

 import re
 re.compile(r'...')

где вы заполняете свой шаблон курса :) Теперь запустите python -m pdb test.py, введите c чтобы продолжить, и он остановится, когда возникнет исключение. В этот момент типа l чтобы увидеть, где вы находитесь в коде. Вы видите, что он терпит неудачу, потому что source.next не во FLAGS. Этот source - это всего лишь ваш шаблон, поэтому вы проверяете, где он терпит неудачу, набрав print source.index.

Кроме того, удаляя это n впереди, шаблон выходит из строя при первом a из <address1>.

(?n странно, я не могу найти его в документации, поэтому он кажется неподдерживаемым расширением. Что касается ?<address1>, я думаю, что это должно быть ?P<address1>. он, как (?i: и если я удалю их и исправлю ?P< материал, я получаю сообщение об несбалансированной скобке в последней скобке.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню