Используемый парсект Адрес улицы, город, штат, почтовый ящик из строки

Проблема. У меня есть поле адреса из базы данных Access, которая была преобразована в Sql Server 2005. В этом поле есть все в одном поле. Мне нужно разобрать отдельные разделы адреса в соответствующие поля в нормализованной таблице. Мне нужно сделать это примерно для 4000 записей, и это должно быть повторяемо.

Предположения:

  • Предположим, что адрес в США (на данный момент)

  • предположить, что строка ввода иногда будет содержать адресата (адресата) и/или второго уличного адреса (то есть Suite B)

  • состояния могут быть сокращены

  • Почтовый индекс может быть стандартным 5-значным или zip + 4

  • в некоторых случаях есть опечатки

ОБНОВЛЕНИЕ: В ответ на поставленные вопросы стандарты не были соблюдены повсеместно, мне нужно сохранить отдельные значения, а не только геокодирование, а ошибки - опечатка (исправлено выше)

Пример данных:

  • а. P. Croll and Son 2299 Lewes-Georgetown Hwy, Джорджтаун, DE 19947

  • 11522 Shawnee Road, Гринвуд DE 19950

  • 144 Kings Highway, S.W. Dover, DE 19901

  • Интегрированная константа. Услуги 2 Penns Way Suite 405 New Castle, DE 19720

  • Humes Realty 33 Bridle Ridge Court, Lewes, DE 19958

  • Николс Раскопки 2742 Pulaski Hwy Newark, DE 19711

  • 2284 Bryn Zion Road, Смирна, DE 19904

  • VEI Dover Crossroads, LLC 1500 Serpentine Road, Suite 100 Baltimore MD 21

  • 580 North Dupont Highway Dover, DE 19901

  • P.O

    . Box 778 Dover, DE 19903

Ответ 1

Я проделал большую работу над этим разбором. Поскольку есть ошибки, вы не получите 100% -ной точности, но есть несколько вещей, которые вы можете сделать, чтобы получить большую часть пути, а затем выполнить визуальный тест BS. Вот общий способ сделать это. Это не код, потому что он довольно академичен, чтобы написать его, нет странности, просто обработка строк.

(Теперь, когда вы разместили некоторые образцы данных, я внес некоторые незначительные изменения)

  • Работайте назад. Начните с почтового индекса, который будет близок к концу, и в одном из двух известных форматов: XXXXX или XXXXX-XXXX. Если это не отображается, вы можете предположить, что находитесь в городе, штат, ниже.
  • Следующее, перед zip, будет состоянием, и оно будет либо в двухбуквенном формате, либо в виде слов. Вы знаете, что это будет, - всего их 50. Кроме того, вы можете озвучить слова, чтобы помочь компенсировать орфографические ошибки.
  • прежде чем это город, и это, вероятно, на той же линии, что и государство. Вы можете использовать базу данных почтового индекса, чтобы проверить город и состояние на основе zip или, по крайней мере, использовать его в качестве детектора BS.
  • Адрес улицы обычно будет одной или двумя строками. Вторая строка, как правило, будет номером набора, если она есть, но также может быть полем PO.
  • Невозможно обнаружить имя на первой или второй строке, но если оно не имеет префикса с числом (или если оно имеет префикс "attn:" или "внимание к:", это может дать вам подсказка о том, является ли это именем или адресной строкой.

Надеюсь, это немного поможет.

Ответ 2

Я считаю, что аутсорсинг проблемы - лучший выбор: отправьте его в геокодер Google (или Yahoo). Геокодер возвращает не только lat/long (которые здесь не представляют интереса), но и богатый синтаксический разбор адреса, с заполненными полями, которые вы не отправляли (включая ZIP + 4 и округ).

Например, разбор "1600 Amphitheatre Parkway, Mountain View, CA" дает

{
  "name": "1600 Amphitheatre Parkway, Mountain View, CA, USA",
  "Status": {
    "code": 200,
    "request": "geocode"
  },
  "Placemark": [
    {
      "address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
      "AddressDetails": {
        "Country": {
          "CountryNameCode": "US",
          "AdministrativeArea": {
            "AdministrativeAreaName": "CA",
            "SubAdministrativeArea": {
              "SubAdministrativeAreaName": "Santa Clara",
              "Locality": {
                "LocalityName": "Mountain View",
                "Thoroughfare": {
                  "ThoroughfareName": "1600 Amphitheatre Pkwy"
                },
                "PostalCode": {
                  "PostalCodeNumber": "94043"
                }
              }
            }
          }
        },
        "Accuracy": 8
      },
      "Point": {
        "coordinates": [-122.083739, 37.423021, 0]
      }
    }
  ]
}

Теперь это разбор!

Ответ 3

Оригинальный плакат, вероятно, долгое время продолжался, но я принял удар по переносу модуля Perl Geo:: StreetAddress: US, используемого geocoder.us на С#, выгрузили его на CodePlex и подумали, что люди, спотыкающиеся по этому вопросу в будущем, могут сочтет это полезным:

US Parser

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

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

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

Ответ 4

Я делал это в прошлом.

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

Ручная обработка занимает около 10 секунд каждый, что означает, что вы можете делать 3600/10 = 360 в час, поэтому 4000 займет около 11-12 часов. Это даст вам высокую точность.

Для автоматизации вам нужна недавняя адресная база данных США, и вы можете настроить свои правила против этого. Я предлагаю не увлекаться регулярным выражением (трудно поддерживать долгосрочные, так много исключений). Пойдите для соответствия 90% к базе данных, сделайте все остальное вручную.

Получите копию стандартов почтовой адресации (USPS) на http://pe.usps.gov/cpim/ftp/pubs/Pub28/pub28.pdf и обратите внимание, что это более 130 страниц. Режимы для реализации будут гайками.

Для международных адресов все ставки отключены. Работники, работающие в США, не смогут проверить.

В качестве альтернативы используйте службу передачи данных. Однако у меня нет рекомендаций.

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

Наконец, когда вы очистили данные, найдите дубликаты.

Ответ 5

Я работаю в домене обработки адресов уже около 5 лет, и на самом деле нет серебряной пули. Правильное решение будет зависеть от значения данных. Если это не очень важно, бросьте его через парсер, как предлагают другие ответы. Если это даже несколько ценно, вам обязательно нужно будет оценить/исправить все результаты анализатора. Если вы ищете полностью автоматизированное, повторяемое решение, вы, вероятно, захотите поговорить с поставщиком коррекции адресов, например Group1 или Trillium.

Ответ 6

После консультации здесь я разработал следующую функцию в VB, которая создает проходимую, хотя и не всегда совершенную (если дано название компании и строка набора, она объединяет данные о наборе и городе). Пожалуйста, не стесняйтесь комментировать/рефакторировать/кричать на меня за нарушение одного из моих собственных правил и т.д.:

Public Function parseAddress(ByVal input As String) As Collection
    input = input.Replace(",", "")
    input = input.Replace("  ", " ")
    Dim splitString() As String = Split(input)
    Dim streetMarker() As String = New String() {"street", "st", "st.", "avenue", "ave", "ave.", "blvd", "blvd.", "highway", "hwy", "hwy.", "box", "road", "rd", "rd.", "lane", "ln", "ln.", "circle", "circ", "circ.", "court", "ct", "ct."}
    Dim address1 As String
    Dim address2 As String = ""
    Dim city As String
    Dim state As String
    Dim zip As String
    Dim streetMarkerIndex As Integer

    zip = splitString(splitString.Length - 1).ToString()
    state = splitString(splitString.Length - 2).ToString()
    streetMarkerIndex = getLastIndexOf(splitString, streetMarker) + 1
    Dim sb As New StringBuilder

    For counter As Integer = streetMarkerIndex To splitString.Length - 3
        sb.Append(splitString(counter) + " ")
    Next counter
    city = RTrim(sb.ToString())
    Dim addressIndex As Integer = 0

    For counter As Integer = 0 To streetMarkerIndex
        If IsNumeric(splitString(counter)) _
            Or splitString(counter).ToString.ToLower = "po" _
            Or splitString(counter).ToString().ToLower().Replace(".", "") = "po" Then
                addressIndex = counter
            Exit For
        End If
    Next counter

    sb = New StringBuilder
    For counter As Integer = addressIndex To streetMarkerIndex - 1
        sb.Append(splitString(counter) + " ")
    Next counter

    address1 = RTrim(sb.ToString())

    sb = New StringBuilder

    If addressIndex = 0 Then
        If splitString(splitString.Length - 2).ToString() <> splitString(streetMarkerIndex + 1) Then
            For counter As Integer = streetMarkerIndex To splitString.Length - 2
                sb.Append(splitString(counter) + " ")
            Next counter
        End If
    Else
        For counter As Integer = 0 To addressIndex - 1
            sb.Append(splitString(counter) + " ")
        Next counter
    End If
    address2 = RTrim(sb.ToString())

    Dim output As New Collection
    output.Add(address1, "Address1")
    output.Add(address2, "Address2")
    output.Add(city, "City")
    output.Add(state, "State")
    output.Add(zip, "Zip")
    Return output
End Function

Private Function getLastIndexOf(ByVal sArray As String(), ByVal checkArray As String()) As Integer
    Dim sourceIndex As Integer = 0
    Dim outputIndex As Integer = 0
    For Each item As String In checkArray
        For Each source As String In sArray
            If source.ToLower = item.ToLower Then
                outputIndex = sourceIndex
                If item.ToLower = "box" Then
                    outputIndex = outputIndex + 1
                End If
            End If
            sourceIndex = sourceIndex + 1
        Next
        sourceIndex = 0
    Next
    Return outputIndex
End Function

Передача функции parseAddress "A. P. Croll and Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947" возвращает:

2299 Lewes-Georgetown Hwy
A. P. Croll & Son  
Georgetown
DE
19947

Ответ 7

У SmartyStreets есть новая функция, которая извлекает адреса из произвольных входных строк. (Примечание: я не работаю на SmartyStreets.)

Он успешно извлек все адреса из ввода примера, указанного в вопросе выше. (Кстати, только 9 из этих 10 адресов действительны.)

Вот некоторые из результатов: enter image description here

И здесь выведенный CSV-вывод этого же запроса:

ID,Start,End,Segment,Verified,Candidate,Firm,FirstLine,SecondLine,LastLine,City,State,ZIPCode,County,DpvFootnotes,DeliveryPointBarcode,Active,Vacant,CMRA,MatchCode,Latitude,Longitude,Precision,RDI,RecordType,BuildingDefaultIndicator,CongressionalDistrict,Footnotes
1,32,79,"2299 Lewes-Georgetown Hwy, Georgetown, DE 19947",N,,,,,,,,,,,,,,,,,,,,,,
2,81,119,"11522 Shawnee Road, Greenwood DE 19950",Y,0,,11522 Shawnee Rd,,Greenwood DE 19950-5209,Greenwood,DE,19950,Sussex,AABB,199505209226,Y,N,N,Y,38.82865,-75.54907,Zip9,Residential,S,,AL,N#
3,121,160,"144 Kings Highway, S.W. Dover, DE 19901",Y,0,,144 Kings Hwy,,Dover DE 19901-7308,Dover,DE,19901,Kent,AABB,199017308444,Y,N,N,Y,39.16081,-75.52377,Zip9,Commercial,S,,AL,L#
4,190,232,"2 Penns Way Suite 405 New Castle, DE 19720",Y,0,,2 Penns Way Ste 405,,New Castle DE 19720-2407,New Castle,DE,19720,New Castle,AABB,197202407053,Y,N,N,Y,39.68332,-75.61043,Zip9,Commercial,H,,AL,N#
5,247,285,"33 Bridle Ridge Court, Lewes, DE 19958",Y,0,,33 Bridle Ridge Cir,,Lewes DE 19958-8961,Lewes,DE,19958,Sussex,AABB,199588961338,Y,N,N,Y,38.72749,-75.17055,Zip7,Residential,S,,AL,L#
6,306,339,"2742 Pulaski Hwy Newark, DE 19711",Y,0,,2742 Pulaski Hwy,,Newark DE 19702-3911,Newark,DE,19702,New Castle,AABB,197023911421,Y,N,N,Y,39.60328,-75.75869,Zip9,Commercial,S,,AL,A#
7,341,378,"2284 Bryn Zion Road, Smyrna, DE 19904",Y,0,,2284 Bryn Zion Rd,,Smyrna DE 19977-3895,Smyrna,DE,19977,Kent,AABB,199773895840,Y,N,N,Y,39.23937,-75.64065,Zip7,Residential,S,,AL,A#N#
8,406,450,"1500 Serpentine Road, Suite 100 Baltimore MD",Y,0,,1500 Serpentine Rd Ste 100,,Baltimore MD 21209-2034,Baltimore,MD,21209,Baltimore,AABB,212092034250,Y,N,N,Y,39.38194,-76.65856,Zip9,Commercial,H,,03,N#
9,455,495,"580 North Dupont Highway Dover, DE 19901",Y,0,,580 N DuPont Hwy,,Dover DE 19901-3961,Dover,DE,19901,Kent,AABB,199013961803,Y,N,N,Y,39.17576,-75.5241,Zip9,Commercial,S,,AL,N#
10,497,525,"P.O. Box 778 Dover, DE 19903",Y,0,,PO Box 778,,Dover DE 19903-0778,Dover,DE,19903,Kent,AABB,199030778781,Y,N,N,Y,39.20946,-75.57012,Zip5,Residential,P,,AL,

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

Ответ 8

Это не решит вашу проблему, но если вам нужны только полные/длинные данные для эти адреса, API Карт Google будет анализировать неформатные адреса довольно хорошо.

Хорошее предложение, вы также можете выполнить запрос CURL для каждого адреса на Картах Google, и он вернет правильно отформатированный адрес. Из этого вы можете повторно выражать свое сердечное содержание.

Ответ 9

+1 на Джеймс А. Розен предложил решение, так как оно хорошо сработало для меня, однако для полных участников этот сайт является увлекательным чтением и лучшей попыткой, которую я видел при оформлении адресов по всему миру: http://www.columbia.edu/kermit/postal.html

Ответ 10

Существуют ли какие-либо стандарты в том, как записываются адреса? Например:

  • Всегда ли запятые или новые линии, отделяющие улицу1 от улицы2 от города от государства от zip?
  • Всегда ли указаны типы адресов (дорога, улица, бульвар и т.д.)? всегда сокращенно? Некоторые из них?
  • Определите "ошибку".

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

Ответ 11

Другой запрос данных образца.

Как уже упоминалось, я бы работал в обратном направлении от zip.

Как только у вас будет zip, я бы запросил zip-базу данных, сохранил результаты и удалил их и zip из строки.

Это оставит вас с беспорядком адреса. Адреса MOST (All?) Начинаются с числа, поэтому найдите первое вхождение числа в оставшейся строке и возьмите все от него до (нового) конца строки. Это будет ваш адрес. Все, что слева от этого числа, вероятно, является адресатом.

Теперь вы должны иметь город, штат и почтовый индекс, хранящиеся в таблице, и, возможно, две строки, адресат и адрес. Для адреса проверьте наличие "Suite" или "Apt". и т.д. и разбивают на два значения (адресные строки 1 и 2).

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

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

Ответ 12

Попробуйте www.address-parser.com. Мы используем их веб-сервис, который вы можете проверить онлайн

Ответ 13

Основываясь на данных выборки:

  • Я бы начал в конце строки. Разберите Zip-код (любой формат). Прочитайте конец первого места. Если почтовый индекс не найден Ошибка.

  • Обрежьте конец, затем пробелы и специальные символы (запятые)

  • Затем перейдите к State, снова используйте Space как разделитель. Возможно, используйте список поиска для проверки двух буквенных кодов состояний и полных имен состояний. Если не найдено допустимого состояния, ошибка.

  • Отрежьте пробелы и запятые от конца снова.

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

  • Если у вас все еще есть символы в строке, переместите все это в поле адреса.

Это не идеально, но это должно быть хорошей отправной точкой.

Ответ 14

Если пользователь введет данные, вы потратите слишком много времени, пытаясь закодировать исключения.

Try:

  • Регулярное выражение для извлечения почтового индекса

  • Поиск почтового индекса (через соответствующую правительственную БД) для получения правильного адреса

  • Получить стажер, чтобы вручную проверить, что новые данные соответствуют старому

Ответ 15

Это не решит вашу проблему, но если вам нужны только полные/длинные данные для этих адресов, API Карт Google будет хорошо разбираться с неформатированными адресами.

Ответ 16

RecogniContact - это объект Windows COM, который анализирует адреса США и Европы. Вы можете попробовать это прямо на http://www.loquisoft.com/index.php?page=8

Ответ 18

Этот тип проблемы трудно решить из-за лежащих в неясности данных.

Вот решение на основе Perl, которое определяет дерево грамматики рекурсивного спуска на основе регулярных выражений для синтаксического анализа многих допустимых комбинаций уличных адресов: http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua/EN/AddressParse.pm. Сюда входят вспомогательные свойства в адресе, например: 12 1st Avenue N Suite № 2 Где-то CA 12345 USA

Он похож на http://search.cpan.org/~timb/Geo-StreetAddress-US-1.03/US.pm, упомянутый выше, но также работает для адресов, которые не из США, таких как Великобритания, Австралия и Канады.

Вот результат для одного из ваших образцов адресов. Обратите внимание, что раздел названия нужно будет удалить сначала из "A. P. Croll and Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947", чтобы уменьшить его до "2299 Lewes-Georgetown Hwy, Georgetown, DE 19947". Это легко достигается путем удаления всех данных до первого числа, найденного в строке.

Non matching part       ''
Error                   '0'
Error descriptions      ''
Case all                '2299 Lewes-Georgetown Hwy Georgetown DE 19947'
COMPONENTS              ''
country                 ''
po_box_type             ''
post_box                ''
post_code               '19947'
pre_cursor              ''
property_identifier     '2299'
property_name           ''
road_box                ''
street                  'Lewes-Georgetown'
street_direction        ''
street_type             'Hwy'
sub_property_identifier ''
subcountry              'DE'
suburb                  'Georgetown'

Ответ 19

Так как есть вероятность ошибки в слове, подумайте об использовании SOUNDEX в сочетании с алгоритмом LCS для сравнения строк, это очень поможет!

Ответ 20

с помощью API Google

$d=str_replace(" ", "+", $address_url);
$completeurl ="http://maps.googleapis.com/maps/api/geocode/xml?address=".$d."&sensor=true"; 
$phpobject = simplexml_load_file($completeurl);
print_r($phpobject);

Ответ 21

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

Единственная проблема, с которой я столкнулся, - всякий раз, когда адрес находится в этом формате P. O. Box 1410 Durham, NC 27702, он возвратил нуль, и поэтому мне пришлось заменить "P. O. Box" на "", после чего он смог разобрать его.

Ответ 22

Службы данных, предоставляемые почтовым индексом, предоставят вам список имен улиц в этом почтовом индексе.

Используйте регулярное выражение для извлечения Zip или City State - найдите правильный или если получится ошибка. вытащите список улиц из источника Исправить город и штат, а затем и уличный адрес. Как только вы получите действительную адресную строку 1, город, штат и почтовый индекс, вы можете сделать предположения по адресной строке 2..3

Ответ 23

Я не знаю, КАК ОСОБЕННО это было бы, но я не видел этого, поэтому я подумал, что буду идти дальше и предлагать это:

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

Ответ 24

Существует порт javascript perl Geo:: StreetAddress:: US package: https://github.com/hassansin/parse-address. Он основан на регулярном выражении и работает достаточно хорошо.