Регулярное выражение для разбора почтовых адресов - PullRequest
9 голосов
/ 13 марта 2009

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

Примечание. Константы STREETTYPES и QUADRANT содержат все соответствующие типы улиц и квадранты соответственно.

Я включил здесь подмножество:

private const string STREETTYPES = @"ALLEY|ALY|ANNEX|AX|ARCADE|ARC|AVENUE|AV|AVE|BAYOU|BYU|BEACH|...";

private const string QUADRANTS = "N|NORTH|S|SOUTH|E|EAST|W|WEST|NE|NORTHEAST|NW|NORTHWEST|SE|SOUTHEAST|SW|SOUTHWEST";

HouseNumber, Quadrant, StreetName и StreetType - все свойства класса.

    private void Parse(string line1)
    {
        HouseNumber = string.Empty;
        Quadrant = string.Empty;
        StreetName = string.Empty;
        StreetType = string.Empty;

        if (!String.IsNullOrEmpty(line1))
        {
            string noPeriodsLine1 = String.Copy(line1);
            noPeriodsLine1 = noPeriodsLine1.Replace(".", "");

            string addressParseRegEx =
                @"(?ix)
            ^
            \s*
            (?:
               (?<housenumber>\d+)
               (?:(?:\s+|-)(?<quadrant>" +
                QUADRANTS +
                @"))?
               (?:(?:\s+|-)(?<streetname>\S+(?:\s+\S+)*?))??
               (?:(?:\s+|-)(?<quadrant>" +
                QUADRANTS + @"))?
               (?:(?:\s+|-)(?<streettype>" + STREETTYPES +
                @"))?
               (?:(?:\s+|-)(?<streettypequalifier>(?!(?:" +
                QUADRANTS +
                @"))(?:\d+|\S+)))?
               (?:(?:\s+|-)(?<streettypequadrant>(" +
                QUADRANTS + @")))??
               (?:(?:\s+|-)(?<suffix>(?:ste|suite|po\sbox|apt)\s*\S*))?
            |
               (?:(?:po|postoffice|post\s+office)\s+box\s+(?<postofficebox>\S+))
            )
            \s*
            $
            ";
            Match match = Regex.Match(noPeriodsLine1, addressParseRegEx);
            if (match.Success)
            {
                HouseNumber = match.Groups["housenumber"].Value;
                Quadrant = (string.IsNullOrEmpty(match.Groups["quadrant"].Value)) ? match.Groups["streettypequadrant"].Value : match.Groups["quadrant"].Value;
                if (match.Groups["streetname"].Captures.Count > 1)
                {
                    foreach (Capture capture in match.Groups["streetname"].Captures)
                    {
                        StreetName += capture.Value + " ";
                    }
                    StreetName = StreetName.Trim();
                }
                else
                {
                    StreetName = (string.IsNullOrEmpty(match.Groups["streetname"].Value)) ? match.Groups["streettypequalifier"].Value : match.Groups["streetname"].Value;
                }
                StreetType = match.Groups["streettype"].Value;

                //if the matched street type is found
                //use the abbreviated version...especially for credit bureau calls
                string streetTypeAbbreviation;
                if (StreetTypes.TryGetValue(StreetType.ToUpper(), out streetTypeAbbreviation))
                {
                    StreetType = streetTypeAbbreviation;
                }
            }
        }

    }

Ответы [ 7 ]

8 голосов
/ 02 мая 2009

Веселитесь с адресами и регулярными выражениями, вас ждет долгая, ужасная поездка.

Вы пытаетесь навести порядок в хаосе.

Для каждого «123 Простого пути» есть «14 1/2 Юга».

Затем, для дополнительного смеха, есть Солт-Лейк-Сити: "855 Юг, 1300 Восток".

Веселитесь с этим.

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

6 голосов
/ 14 марта 2009

Я думаю, вы должны уточнить свой сценарий использования.

Если вы не находитесь в очень, очень ограниченном сценарии, когда вы знаете, что адреса были введены в соответствии со строгой схемой, анализ адресов для контента является чрезвычайно трудной проблемой и, как правило, довольно бесполезным (если это не raison d'être вашего заявления).

Если вы ограничены какой-либо конкретной страной, в которой есть очень конкретные соглашения для написания адресов, то использование этих регулярных выражений может помочь вам на 90%.
Однако, как только вы начинаете принимать иностранные адреса, вы облажались.
Даже если вы ориентированы на США, есть большая вероятность, что вам, возможно, придется принимать адреса от граждан США, живущих за границей, например.

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

Несколько вещей, которые мешают анализу адресов:

  • почтовые индексы (почтовые индексы) иногда размещаются до, после или могут вообще не существовать.
  • почтовые индексы подчиняются строгим правилам: почтовый индекс из 10 цифр, вероятно, легко определить как недействительный, но как насчет несуществующего? Как насчет других кодов, таких как, например, используемые в Великобритании?
  • Как насчет такого места, как Гонконг, где вы можете написать адрес на английском, традиционном китайском или мандаринском языке?
  • Что делать, если вы прекрасно разделите свой адрес и напишите его по порядку?
  • , даже если вы просто анализируете адреса в США, есть по крайней мере несколько способов описать почтовый ящик: вы также можете использовать до востребования , общая доставка , а затем необходимо добавить 4-значный код к почтовому индексу, который обычно, вероятно, не будет вообще ...

Итог

Если получение адресов в разбираемом формате действительно важно, будьте уверены на 100%, что вы можете получить все возможные комбинации правильно, или у вас будет процент отказов, который будет означать разочарование пользователей и убытки от продаж.
Если у вас нет 100% охвата случая, не применяйте строгие правила к пользователю.
Я не могу сосчитать количество сайтов, с которых я отказался от покупки, потому что им потребовался бы почтовый индекс, если в месте, где я живу, нет ни одного.

Извините за напыщенную речь, но я думаю, что важно, чтобы люди, желающие выполнить проверку адреса и анализ, усердно думали о том, во что они попадают.

6 голосов
/ 13 марта 2009

Я не знаю, в какой стране вы находитесь, но если вы находитесь в США и хотите потратить немного денег на проверку адреса, вы можете купить соответствующие продукты USPS здесь . И здесь является хорошим местом для поиска бесплатных списков слов из USPS для ожидаемых слов и сокращений. Я уверен, что подобные страницы доступны для других стран.

2 голосов
/ 02 июня 2010

Это на самом деле работает довольно хорошо, за исключением того, что не тянет номера квартир. Мы работаем над этим. Это также немного кашлянуло, когда у нас был адрес 769 Branch Ave. Конечно, "ветка" - это один из видов улиц, которые она ищет. Все восходит к тому, что порядок из хаоса. Мы знаем, что это сломается здесь и там.

1 голос
/ 18 декабря 2013

Если кто-то столкнется с этой проблемой в 2013/2014 :) Вы можете использовать Google Geocode API. это обеспечивает больше функциональности, чем просто регулярное выражение - вы можете даже получить широту / долготу для адреса. И его бесплатно

Для примера адреса -

http://maps.googleapis.com/maps/api/geocode/xml?address=2520%20Cohasset%20Rd%20-%20Chico%2C%20CA%2095973-1307%20530-893-1300%20%20&sensor=false

enter image description here

0 голосов
/ 20 сентября 2009

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

"NE", "N.E", "N E", "N.E.", "N.E", "North East", "North East"

поэтому я использую следующее сопоставление с образцом, которое должно отлавливать все квалификаторы направления независимо от того, как они выражены:

\b(?:(?:[nesw]\.? ?){0,2}|(?:north|no\.|east|south|so\.|west){0,2})\b

Конечно, контекст также важен, так как «нет» будет соответствовать этому. Но «NE» для Небраски будет соответствовать любому из них, так что вам действительно нужно быть осторожным с тем, что слева и справа в вашем широком выражении. Мне приходится составлять списки слов, которые обычно появляются в текстах адресов, которые не являются компонентами адресов, таких как «рядом, на улице, в, поперек» и т. Д.

Это очень сложная проблема, и я согласен, что Солт-Лейк-Сити - сука. Помимо наличия формата двойного направления / координаты, они также составляют его, ссылаясь на такие вещи, как «3700 North 5300 East Arborville Way», где на улицы можно ссылаться по имени, номеру или обоим.

0 голосов
/ 02 мая 2009

Я пытался заставить это работать, но кажется, что у вас есть статический член класса StreetTypes, который не включен. Кажется, что это работает, за исключением этого, но я не могу сделать много испытаний без него.

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