Problem: Mam pole adresu z bazy danych Access, która została przekonwertowana na Sql Server 2005. To pole zawiera wszystko w jednym polu. Muszę wydzielić poszczególne sekcje adresu do odpowiednich pól w znormalizowanej tabeli. Muszę to zrobić dla około 4000 rekordów i musi to być powtarzalne.
Założenia:
Przyjmij adres w USA (na razie)
załóżmy, że ciąg wejściowy będzie czasem zawierał adresata (adresowaną osobę) i / lub drugi adres (np. lokal B)
stany mogą być skracane
Kod pocztowy może mieć standardowe 5 cyfr lub kod pocztowy + 4
w niektórych przypadkach występują literówki
AKTUALIZACJA: W odpowiedzi na zadane pytania standardy nie były powszechnie przestrzegane, muszę przechowywać poszczególne wartości, a nie tylko geokodować, a błędy oznaczają literówkę (poprawione powyżej)
Przykładowe dane:
AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947
11522 Shawnee Road, Greenwood DE 19950
144 Kings Highway, SW Dover, DE 19901
Konst. Usługi 2 Penns Way Suite 405 New Castle, DE 19720
Humes Realty 33 Bridle Ridge Court, Lewes, DE 19958
Nichols Excavation 2742 Pulaski Hwy Newark, DE 19711
2284 Bryn Zion Road, Smyrna, DE 19904
VEI Dover Crossroads, LLC 1500 Serpentine Road, Suite 100 Baltimore MD 21
580 North Dupont Highway Dover, DE 19901
PO Box 778 Dover, DE 19903
źródło
Odpowiedzi:
Wykonałem dużo pracy nad tego rodzaju analizą. Ponieważ są błędy, nie uzyskasz 100% dokładności, ale jest kilka rzeczy, które możesz zrobić, aby uzyskać jak najwięcej z nich, a następnie wykonać wizualny test BS. Oto ogólny sposób, jak to zrobić. To nie jest kod, ponieważ pisanie go jest dość akademickie, nie ma dziwnych rzeczy, po prostu dużo obsługi ciągów.
(Teraz, gdy opublikowałeś kilka przykładowych danych, wprowadziłem kilka drobnych zmian)
Mam nadzieję, że to trochę pomoże.
źródło
Myślę, że najlepszym rozwiązaniem jest outsourcing: wyślij go do geokodera Google (lub Yahoo). Geokoder zwraca nie tylko szerokość / długość (które nie są tutaj interesujące), ale także bogatą analizę adresu, z wypełnionymi polami, których nie wysłałeś (w tym ZIP + 4 i hrabstwo).
Na przykład analiza wyników „1600 Amphitheatre Parkway, Mountain View, CA” daje wyniki
Teraz to jest możliwe do przeanalizowania!
źródło
Oryginalny plakat prawdopodobnie już dawno się rozwinął , ale próbowałem przenieść moduł Perl Geo :: StreetAddress: US używany przez geocoder.us do C #, porzuciłem go na CodePlex i myślę, że ludzie, którzy natkną się na to pytanie w przyszłości, mogą uważaj to za przydatne:
Parser adresów w USA
Na stronie domowej projektu staram się opowiedzieć o jego (bardzo realnych) ograniczeniach. Ponieważ nie jest on wspierany przez bazę danych USPS zawierającą prawidłowe adresy, analiza może być niejednoznaczna i nie może potwierdzić ani zaprzeczyć ważności podanego adresu. Może po prostu spróbować wyciągnąć dane z łańcucha.
Jest to przeznaczone do przypadku, gdy potrzebujesz uzyskać zestaw danych głównie w odpowiednich polach lub chcesz udostępnić skrót do wprowadzania danych (pozwalając użytkownikom wkleić adres w polu tekstowym zamiast przechodzić między wieloma polami). To jest nie oznaczało dla sprawdzenia możliwości dostarczenia adresu.
Nie próbuje analizować czegokolwiek powyżej linii ulicy, ale prawdopodobnie można by pomieszać z wyrażeniem regularnym, aby uzyskać coś dość bliskiego - prawdopodobnie po prostu przerwałbym to pod numerem domu.
źródło
Robiłem to w przeszłości.
Albo zrób to ręcznie (stwórz fajny interfejs użytkownika, który pomoże użytkownikowi to zrobić szybko) lub zautomatyzuj i sprawdź ostatnią bazę adresów (musisz to kupić) i ręcznie obsłuż błędy.
Ręczna obsługa zajmie około 10 sekund, co oznacza, że możesz zrobić 3600/10 = 360 na godzinę, więc 4000 powinno zająć około 11-12 godzin. Zapewni to wysoki wskaźnik dokładności.
Do automatyzacji potrzebujesz najnowszej bazy danych adresów w USA i dostosuj swoje reguły do tego. Proponuję nie wymyślać wyrażenia regularnego (trudne do utrzymania w dłuższej perspektywie, tak wiele wyjątków). Wybierz 90% zgodności z bazą danych, resztę zrób ręcznie.
Pobierz kopię Standardów adresowania poczty (USPS) pod adresem http://pe.usps.gov/cpim/ftp/pubs/Pub28/pub28.pdf i zauważ, że ma ponad 130 stron. Regexes do wdrożenia to byłoby szaleństwo.
W przypadku adresów międzynarodowych wszystkie zakłady są wyłączone. Pracownicy z USA nie byliby w stanie zweryfikować.
Możesz też skorzystać z usługi transmisji danych. Nie mam jednak żadnych zaleceń.
Co więcej: kiedy wysyłasz rzeczy pocztą (do tego to służy, prawda?) Upewnij się, że umieściłeś na kopercie informację o „żądaniu korekty adresu” (we właściwym miejscu) i zaktualizuj bazę danych. (Zrobiliśmy prosty GUI dla pracownika recepcji, który faktycznie sortuje pocztę)
Wreszcie, po wyczyszczeniu danych, poszukaj duplikatów.
źródło
Po poradach tutaj, opracowałem następującą funkcję w VB, która tworzy zadowalające, choć nie zawsze doskonałe (jeśli podana jest nazwa firmy i linia zestawu, łączy pakiet i miasto) użyteczne dane. Nie krępuj się komentować / refaktoryzować / wrzeszczeć na mnie za złamanie jednej z moich własnych zasad itp .:
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
Przekazanie
parseAddress
funkcji „AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947” zwraca:źródło
Pracuję w domenie przetwarzania adresów od około 5 lat i naprawdę nie ma tu żadnej srebrnej kuli. Prawidłowe rozwiązanie będzie zależeć od wartości danych. Jeśli nie jest to zbyt wartościowe, przerzuć je przez parser, jak sugerują inne odpowiedzi. Jeśli jest to choć trochę wartościowe, na pewno będziesz potrzebować człowieka do oceny / poprawienia wszystkich wyników parsera. Jeśli szukasz w pełni zautomatyzowanego, powtarzalnego rozwiązania, prawdopodobnie chcesz porozmawiać z dostawcą korekty adresu, takim jak Group1 lub Trillium.
źródło
SmartyStreets ma nową funkcję, która wyodrębnia adresy z dowolnych ciągów wejściowych. (Uwaga: nie pracuję w SmartyStreets.)
Pomyślnie wyodrębnił wszystkie adresy z przykładowych danych wejściowych podanych w powyższym pytaniu. (Nawiasem mówiąc, tylko 9 z tych 10 adresów jest ważnych).
Oto niektóre wyniki:
A oto wynik tego samego żądania w formacie 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,
Byłem programistą, który pierwotnie napisał usługę. Algorytm, który zaimplementowaliśmy, różni się nieco od wszelkich konkretnych odpowiedzi, ale każdy wyodrębniony adres jest weryfikowany za pomocą interfejsu API wyszukiwania adresów, więc możesz być pewien, czy jest prawidłowy, czy nie. Każdy zweryfikowany wynik jest gwarantowany, ale wiemy, że inne wyniki nie będą doskonałe, ponieważ, jak zostało to wyraźnie wyjaśnione w tym wątku, adresy są nieprzewidywalne, nawet dla ludzi czasami.
źródło
Dobra sugestia, alternatywnie możesz wykonać żądanie CURL dla każdego adresu w Mapach Google, a to zwróci odpowiednio sformatowany adres. Od tego możesz regex do syta.
źródło
+1 do rozwiązania sugerowanego przez Jamesa A. Rosena, ponieważ działało dobrze dla mnie, jednak dla kompletujących ta strona jest fascynującą lekturą i najlepszą próbą, jaką widziałem w dokumentowaniu adresów na całym świecie: http://www.columbia.edu/kermit /postal.html
źródło
Czy istnieją jakiekolwiek standardy dotyczące sposobu zapisywania adresów? Na przykład:
Moja ogólna odpowiedź to seria wyrażeń regularnych, chociaż złożoność tego zależy od odpowiedzi. A jeśli w ogóle nie ma spójności, możesz osiągnąć tylko częściowy sukces za pomocą Regex (tj: odfiltrować kod pocztowy i stan), a resztę będziesz musiał zrobić ręcznie (lub przynajmniej przejść przez resztę bardzo uważnie, aby upewnić się, że zauważysz błędy).
źródło
Kolejna prośba o przykładowe dane.
Jak już wspomniałem, pracowałbym tyłem do zamka błyskawicznego.
Gdy już masz plik zip, zapytałem o bazę danych zip, zapisałem wyniki i usunąłem je oraz zip z ciągu.
To pozostawi bałagan adresowy. WIĘKSZOŚĆ (wszystkie?) Adresy zaczyna się od liczby, więc znajdź pierwsze wystąpienie liczby w pozostałym ciągu i pobierz wszystko od niej do (nowego) końca ciągu. To będzie twój adres. Cokolwiek na lewo od tej liczby jest prawdopodobnie adresatem.
Powinieneś teraz mieć zapisane miasto, stan i kod pocztowy w tabeli i prawdopodobnie dwa ciągi znaków, adresata i adres. Aby uzyskać adres, sprawdź, czy istnieje „Suite” lub „Apt”. itd. i podziel to na dwie wartości (linie adresu 1 i 2).
Dla adresata wybrałbym i chwycił ostatnie słowo tego ciągu jako nazwisko, a resztę umieściłem w polu imię. Jeśli nie chcesz tego robić, musisz sprawdzić na początku powitanie (Pan, Pani, Dr itp.) I poczynić pewne założenia na podstawie liczby spacji, co do tego, jak jest to imię składający się.
Nie sądzę, aby można było przeprowadzić analizę ze 100% dokładnością.
źródło
Spróbuj www.address-parser.com . Korzystamy z ich usługi internetowej, którą możesz przetestować online
źródło
Na podstawie przykładowych danych:
Zacząłbym na końcu struny. Przeanalizuj kod pocztowy (w dowolnym formacie). Przeczytaj koniec do pierwszej spacji. Jeśli nie znaleziono kodu pocztowego Błąd.
Następnie przytnij koniec do spacji i znaków specjalnych (przecinków)
Następnie przejdź do State, ponownie użyj spacji jako separatora. Może użyj listy odnośników, aby zweryfikować dwuliterowe kody stanów i pełne nazwy stanów. Jeśli nie znaleziono prawidłowego stanu, wystąpił błąd.
Ponownie przytnij spacje i przecinki od końca.
Miasto robi się trudne, właściwie użyłbym tutaj przecinka, ryzykując uzyskanie zbyt dużej ilości danych w mieście. Poszukaj przecinka lub początku wiersza.
Jeśli nadal masz znaki w ciągu, umieść to wszystko w polu adresu.
To nie jest idealne, ale powinno to być całkiem dobry punkt wyjścia.
źródło
Jeśli są to dane wprowadzone przez człowieka, spędzisz zbyt dużo czasu na próbach kodowania wokół wyjątków.
Próbować:
Wyrażenie regularne do wyodrębnienia kodu pocztowego
Wyszukiwanie kodu pocztowego (za pośrednictwem odpowiedniej rządowej bazy danych) w celu uzyskania prawidłowego adresu
Poproś stażystę, aby ręcznie zweryfikował, czy nowe dane są zgodne ze starymi
źródło
To nie rozwiąże problemu, ale jeśli potrzebujesz tylko danych o szerokości / długości dla tych adresów, interfejs API Map Google całkiem dobrze przeanalizuje niesformatowane adresy.
źródło
RecogniContact to obiekt COM systemu Windows, który analizuje adresy amerykańskie i europejskie. Możesz to wypróbować bezpośrednio na http://www.loquisoft.com/index.php?page=8
źródło
Możesz to sprawdzić !! http://jgeocoder.sourceforge.net/parser.html Działał dla mnie jak urok.
źródło
Tego typu problem jest trudny do rozwiązania ze względu na niejasności w danych.
Oto rozwiązanie oparte na Perlu, które definiuje drzewo gramatyki rekurencyjnego pochodzenia opartego na wyrażeniach regularnych w celu przeanalizowania wielu prawidłowych kombinacji adresów ulic: http://search.cpan.org/~kimryan/Lingua-EN-AddressParse-1.20/lib/Lingua /EN/AddressParse.pm . Obejmuje to pod-nieruchomości w ramach adresu, takiego jak: 12 1st Avenue N Suite # 2 Somewhere CA 12345 USA
Jest podobny do http://search.cpan.org/~timb/Geo-StreetAddress-US-1.03/US.pm wspomnianego powyżej, ale działa również w przypadku adresów spoza USA, takich jak Wielka Brytania, Australia i Kanada.
Oto wynik dla jednego z przykładowych adresów. Należy zauważyć, że sekcja dotycząca nazwy musiałaby zostać najpierw usunięta z „AP Croll & Son 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947”, aby zredukować ją do „2299 Lewes-Georgetown Hwy, Georgetown, DE 19947”. Można to łatwo osiągnąć, usuwając wszystkie dane aż do pierwszej liczby znalezionej w ciągu.
źródło
Ponieważ istnieje ryzyko błędu w słowie, pomyśl o użyciu SOUNDEX w połączeniu z algorytmem LCS do porównywania łańcuchów, to bardzo pomoże!
źródło
za pomocą Google API
źródło
Dla programistów ruby lub rails dostępny jest niezły klejnot o nazwie street_address . Używałem tego w jednym z moich projektów i robi to, czego potrzebuję.
Jedynym problemem, jaki miałem, było to, że zawsze, gdy adres jest w tym formacie, zwracał
P. O. Box 1410 Durham, NC 27702
zero i dlatego musiałem zamienić „PO Box” na „”, a następnie był w stanie go przeanalizować.źródło
Istnieją usługi transmisji danych, w przypadku których dany kod pocztowy poda listę nazw ulic w tym kodzie pocztowym.
Użyj wyrażenia regularnego, aby wyodrębnić kod pocztowy lub stan miasta - znajdź poprawny lub, jeśli błąd, uzyskaj oba. pobrać listę ulic ze źródła danych Popraw miasto i stan, a następnie adres. Gdy uzyskasz prawidłowy wiersz adresu 1, miasto, stan i kod pocztowy, możesz przyjąć założenia w wierszu adresu 2..3
źródło
Nie wiem, JAKIE byłoby to wykonalne, ale nie widziałem tego wspomnianego, więc pomyślałem, że pójdę dalej i zasugeruję:
Jeśli przebywasz wyłącznie w Stanach Zjednoczonych ... uzyskaj ogromną bazę danych wszystkich kodów pocztowych, stanów, miast i ulic. Teraz poszukaj ich w swoich adresach. Możesz zweryfikować znalezione informacje, sprawdzając, czy np. Znalezione miasto istnieje w stanie, które znalazłeś, lub sprawdzając, czy znaleziona ulica istnieje w mieście, które znalazłeś. Jeśli nie, prawdopodobnie John nie jest ulicą Jana, ale jest to nazwisko adresata ... Zasadniczo, uzyskaj jak najwięcej informacji i porównaj z nimi swoje adresy. Ekstremalnym przykładem byłoby pobranie LISTY WSZYSTKICH ADRESÓW W USA A, a następnie znalezienie tego, który najlepiej pasuje do każdego z Twoich adresów ...
źródło
Istnieje port javascript pakietu Perl Geo :: StreetAddress :: US: https://github.com/hassansin/parse-address . Jest oparty na wyrażeniach regularnych i działa dość dobrze.
źródło