Analizar utilizable Dirección de la Calle, Ciudad, Estado, código Postal a partir de una cadena [cerrado]

StackOverflow https://stackoverflow.com/questions/16413

Pregunta

Problema:Tengo un campo de direcciones de una base de datos de Access que se ha convertido en Sql Server 2005.Este campo lo tiene todo en un solo campo.Es necesario analizar las secciones individuales de la dirección en sus correspondientes campos en una tabla normalizada.Necesito hacer esto para aproximadamente 4.000 registros y debe ser repetible.

Supuestos:

  1. Asumir una dirección en los estados unidos (por ahora)

  2. suponga que la cadena de entrada a veces contienen un destinatario (la persona que está siendo abordado) y/o una segunda dirección de la calle (es decir,Suite B)

  3. los estados pueden ser abreviadas

  4. el código postal podría ser de 5 dígitos o zip+4

  5. hay erratas en algunos casos

ACTUALIZACIÓN:En respuesta a las preguntas planteadas, las normas no fueron universalmente seguido, tengo necesidad de almacenar los valores individuales, no sólo de geocodificación y errores medios error tipográfico (corregido arriba)

Datos De Ejemplo:

  • A.P.Croll y el Hijo 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947

  • 11522 Shawnee Carretera, Bosque DE 19950

  • 144 Reyes de la Carretera, SWDover, DE 19901

  • Sistema Integrado De Const.Servicios 2 Penns Way, Suite 405 New Castle, DE 19720

  • Humes Realty 33 Brida Cresta de la Corte, Lewes, DE 19958

  • Nichols Excavación 2742 Pulaski Hwy Newark, DE 19711

  • 2284 Bryn Sión de la Carretera, Smyrna, DE 19904

  • VEI Dover Encrucijada, LLC 1500 Serpentina Road, Suite 100 Baltimore MD 21

  • 580 del Norte Dupont Carretera de Dover, DE 19901

  • P. O.Cuadro 778 Dover, DE 19903

¿Fue útil?

Solución

He hecho un montón de trabajo en este tipo de análisis.Porque hay errores que no se consigue el 100% de precisión, pero hay algunas cosas que usted puede hacer para conseguir que la mayor parte del camino, y, a continuación, hacer un visual BS prueba.Aquí está el general de manera de ir sobre ella.No es código, porque es bastante académico de escribir, no hay ninguna rareza, sólo un montón de manejo de cadenas de caracteres.

(Ahora que ya he publicado algunos datos de ejemplo, he hecho algunos cambios menores)

  1. Trabajar hacia atrás.Empezar desde el código postal, que estará cerca de la final, y en uno de los dos formatos conocidos:XXXXX o XXXXX-XXXX.Si este no aparece, usted puede asumir que usted está en la ciudad, el estado parte, a continuación.
  2. La siguiente cosa, antes de que el zip, va a ser el estado, y va a ser en un formato de carta, o como las palabras.Usted sabe lo que esta será, también, hay sólo 50 de ellos.También, usted podría soundex las palabras para ayudar a compensar los errores de ortografía.
  3. antes de que es la ciudad, y es probablemente en la misma línea que la del estado.Usted podría utilizar un código postal de la base de datos para verificar la ciudad y el estado basado en el zip, o al menos usarlo como detector de BS.
  4. La dirección general será de una o dos líneas.La segunda línea será generalmente el número de habitación si es que la hay, pero también podría ser un apartado postal.
  5. Va a ser casi imposible detectar un nombre en la primera o segunda línea, aunque si no es precedido de un número (o si es el prefijo "attn:" o "atención:" se podría dar una pista de si es un nombre o una línea de dirección.

Espero que esto ayude un poco.

Otros consejos

Creo que la externalización del problema es la mejor apuesta:enviar a Google (o Yahoo) geocoder.El geocoder no solo devuelve la lat/long (que no son de interés aquí), pero también un rico análisis de la dirección, con campos llenos de que usted no envió (incluyendo ZIP+4 y el condado).

Por ejemplo, el análisis de "1600 Amphitheatre Parkway, Mountain View, CA" da

{
  "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]
      }
    }
  ]
}

Ahora que parseable!

El cartel original, probablemente ha tiempo pasó, pero me tomó una puñalada en el traslado del Perl Geo::StreetAddress:US módulo utilizado por geocoder.nosotros a C#, objeto de dumping en CodePlex, y creo que a la gente tropezar a través de esta cuestión en el futuro puede resultar útil:

NOS Analizador de Dirección

En la página principal del proyecto, que yo trato de hablar acerca de su (muy real) limitaciones.Ya que no es respaldado por el USPS base de datos de direcciones de la calle, el análisis puede ser ambiguo y no puede confirmar ni negar la validez de una dirección determinada.Puede simplemente tratar de extraer los datos de la cadena.

Está pensado tanto para el caso cuando usted necesita para obtener un conjunto de datos en su mayoría en el derecho campos, o si desea proporcionar un acceso directo a los datos de entrada (que permite a los usuarios pegar una dirección en un cuadro de texto en lugar de tabulación entre varios campos).Es no significó para la verificación de la entrega de una dirección.

No intento analizar cualquier cosa por encima de la línea de la calle, pero podría diddle con la expresión regular para obtener algo razonablemente cerca--probablemente me acaba de romper en el número de la casa.

He hecho esto en el pasado.

Hacerlo manualmente, (construir una agradable interfaz gráfica de usuario que ayuda al usuario a hacerlo rápidamente) o automatizado y verificar contra una reciente base de datos de direcciones (tienes que comprar) y manual de manejo de errores.

Manual de manejo tomará alrededor de 10 segundos cada uno, lo que significa que usted puede hacer 3600/10 = 360 por hora, así 4000 debe tomar aproximadamente de 11 a 12 horas.Esto le dará una alta tasa de precisión.

Para la automatización, que necesidad un reciente NOS de la dirección de la base de datos, y modificar su reglamento en contra de eso.Sugiero no va de lujo en el regex (difícil de mantener a largo plazo, por lo que muchas excepciones).Ir para el 90% de coincidencia con la base de datos, hacer el resto de forma manual.

Hacer llegar una copia de la Postal de Abordar los Estándares (USPS) http://pe.usps.gov/cpim/ftp/pubs/Pub28/pub28.pdf y el aviso es de 130+ páginas de largo.Expresiones regulares para implementar que sería frutos secos.

Internacional de direcciones, todas las apuestas están apagadas.NOSOTROS los trabajadores no sería capaz de validar.

Alternativamente, puedes utilizar un servicio de datos.Tengo, sin embargo, no hay recomendaciones.

Además:cuando usted envía a cabo las cosas en el correo electrónico (que es lo que es, ¿verdad?) asegúrese de poner el "solicita corrección de dirección" en el sobre (en el lugar correcto) y actualización la base de datos.(Hemos hecho una sencilla interfaz gráfica de usuario de la persona en la recepción para hacer eso;la persona que realmente se ordena a través de correo)

Finalmente, cuando haya fregado de datos, buscar duplicados.

Después de que el consejo aquí, he elaborado la siguiente función en VB que crea pasable, aunque no siempre es perfecta (si el nombre de una empresa y una suite línea se dan, se combina la suite y de la ciudad) datos utilizables.Por favor, siéntase libre de comentar/refactorizar/gritar a mí para romper uno de mis propias reglas, etc.:

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

Pasando el parseAddress la función de "A.P.Croll y el Hijo 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947" devuelve:

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

He estado trabajando en la dirección de procesamiento de dominio por 5 años ya, y realmente no hay bala de plata.La solución correcta es la que va a depender del valor de los datos.Si no es muy valiosa, tirar de ella a través de un analizador como las otras respuestas sugieren.Si es algo valioso que definitivamente se necesita para tener un humano evaluar o corregir todos los resultados del analizador.Si usted está buscando un sistema totalmente automatizado, repetible solución, usted probablemente querrá hablar con una corrección de la dirección del proveedor como Grupo1 o Trillium.

SmartyStreets tiene una nueva función que extrae direcciones arbitrarias de las cadenas de entrada.(Nota:Yo no trabajo en SmartyStreets.)

Se logró extraer todas las direcciones de la muestra de entrada dada en la pregunta anterior.(Por cierto, sólo 9 de los 10 direcciones son válidas.)

He aquí algunos de los resultados:enter image description here

Y aquí está la salida con formato CSV de que la misma petición:

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,

Yo era el desarrollador que originalmente escribió el servicio.El algoritmo que hemos implementado es un poco diferente de cualquier respuestas específicas aquí, pero cada extraído dirección se verifica en contra de la dirección de búsqueda de la API, así que usted puede estar seguro de si es válido o no.Cada verificado el resultado está garantizado, pero sabemos que los otros resultados no ser perfecto, porque, como se ha hecho claro en este hilo, las direcciones son impredecibles, incluso para los seres humanos a veces.

Esto no resuelve tu problema, pero si usted sólo necesita lat/long datos para estas direcciones, la API de Google Maps analizará la no-formato de direcciones bastante bien.

Buena sugerencia, alternativamente, usted puede ejecutar una solicitud CURL para cada dirección en Google Maps y se le devolverá el formato correcto de la dirección.A partir de eso, usted puede regex al contenido de su corazón.

+1 en James A.Rosen de la propuesta de solución como ha funcionado bien para mí, sin embargo, para los coleccionistas de tito este sitio es una lectura fascinante y el mejor intento he visto en la documentación de las direcciones de todo el mundo: http://www.columbia.edu/kermit/postal.html

Hay algunos estándares en todo en la forma en que las direcciones se registran?Por ejemplo:

  1. Hay siempre comas o nuevas líneas de separación de street1 de street2 de la ciudad de estado desde el zip?
  2. Son tipos de dirección, carretera, calle, boulevard, etc) siempre enunciados?siempre abreviado?Algunos de cada uno?
  3. Definir "error".

Mi respuesta general es una serie de Expresiones Regulares, aunque la complejidad de este depende la respuesta.Y si no hay coherencia en todo, entonces sólo puede ser capaz de lograr un éxito parcial con una Expresión regular (es decir:el filtrado de código postal y estado) y tendrá que hacer el resto con la mano (o al menos pasar por el resto muy cuidadosamente para asegurarse de ver los errores).

Otra solicitud de datos de la muestra.

Como se ha mencionado me gustaría trabajar hacia atrás desde el zip.

Una vez que usted tiene un zip me gustaría consultar una postal de base de datos, guardar los resultados, y eliminar de ellos y de la cremallera de la cadena.

Que te dejará con la dirección lío.La MAYORÍA (Todos?) direcciones de inicio con un número para encontrar la primera aparición de un número en el resto de la cadena y agarrar todo a la (nueva) final de la cadena.Que será su dirección.Nada a la izquierda de es probable que el número de un destinatario.

Ahora debe tener la Ciudad, Estado y Zip almacenados en una tabla y, posiblemente, dos cadenas, destinatario y dirección.Para la dirección, comprobar la existencia de la "Suite" o "Apt". etc.y la división en dos valores (dirección de las líneas 1 y 2).

Para el destinatario me gustaría punt y agarrar la última palabra de esa cadena como el último nombre y poner el resto en el campo nombre.Si usted no quiere hacer eso, usted necesita comprobar el saludo (Sr., Sra., Dr., etc.) en el inicio y hacer algunas suposiciones basadas en el número de espacios como la manera en que el nombre es compuesto.

Yo no creo que haya ninguna manera se puede analizar con 100% de precisión.

Trate de www.address-parser.com.Hacemos uso de su servicio web, que usted puede probar en línea

Según los datos de ejemplo:

  1. Me gustaría empezar por el final de la cadena.Analizar un código Postal (cualquiera de los dos formatos).De fin de lectura para primer espacio.Si no hay Código Postal se encuentra el Error.

  2. Recortar el final, entonces para espacios y caracteres especiales (comas)

  3. A continuación, pasar a Estado, de nuevo, utilice el Espacio como delimitador.Tal vez el uso de una lista de búsqueda para validar 2 de la carta de los códigos de estado, y completa del estado de nombres.Si no hay un estado que se encuentra, y el error.

  4. Recorte de espacios y comas de la final de nuevo.

  5. La ciudad se pone difícil, en realidad yo lo use una coma aquí, a riesgo de llegar demasiado de datos en la ciudad.Busque la coma, o principio de la línea.

  6. Si usted todavía tiene caracteres en la cadena, meter todo eso en un campo de dirección.

Esto no es perfecto, pero debería ser un buen punto de partida.

Si es humano datos ingresados, entonces usted va a pasar mucho tiempo tratando de código alrededor de las excepciones.

Probar:

  1. Expresión Regular para extraer el código postal

  2. El código postal de búsqueda (mediante el correspondiente gobierno DB) para obtener la dirección correcta

  3. Obtener una pasantía para comprobar manualmente los nuevos datos coincide con la edad

Esto no resuelve tu problema, pero si usted sólo necesita lat/long datos para estas direcciones, la API de Google Maps va a analizar no-formato de direcciones bastante bien.

RecogniContact es un Windows objeto COM que analiza NOSOTROS y direcciones Europeas.Usted puede tratar a la derecha en http://www.loquisoft.com/index.php?page=8

Es posible que desee comprobar esto!! http://jgeocoder.sourceforge.net/parser.html Trabajó como un encanto para mí.

Este tipo de problema es difícil de resolver, debido a ciertas ambigüedades en los datos.

Aquí es un Perl solución basada en la que define una relación de recurrencia para el descenso de la gramática de árbol basado en expresiones regulares para analizar muchos de combinación válida de las direcciones de la calle: http://search.cpan.org/~kimryan/Lingua-ES-AddressParse-1.20/lib/Lengua/ES/AddressParse.pm .Esto incluye sub propiedades dentro de una dirección como:12 Avenida 1 N Suite # 2 en Algún lugar de CA 12345, estados UNIDOS

Es similar a http://search.cpan.org/~timb/Geo-StreetAddress-US-1.03/NOSOTROS.pm mencionado anteriormente, pero también funciona para las direcciones que no son de los estados UNIDOS, tales como el reino unido, Australia y Canadá.

Aquí está la salida de uno de sus muestras direcciones.Tenga en cuenta que el nombre de la sección que tendría que quitarse primero de "A.P.Croll y el Hijo 2299 Lewes-Georgetown Hwy, Georgetown, DE 19947" reducir a la "2299 Lewes-Georgetown Hwy, Georgetown, DE 19947".Esto se logra fácilmente mediante la eliminación de todos los datos hasta el primer número se encuentra en la cadena.

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'

Ya no hay posibilidad de error en la palabra, pensar en el uso de SOUNDEX combinado con LCS algoritmo para comparar cadenas, esto va a ayudar mucho !

el uso de la API de 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);

Para ruby o rails desarrolladores hay una bonita joya disponible de la llamada street_address.He estado usando esto en uno de mis proyecto y se hace el trabajo que necesito.

El único Problema que tuve fue cuando una dirección es en este formato P. O. Box 1410 Durham, NC 27702 se devuelve nil y por lo tanto he tenido que cambiar ", Pág.O.Cuadro de" con " y después de esto se fueron capaces de analizarlo.

Hay servicios de datos que, dado un código postal le dará la lista de los nombres de las calles en ese código postal.

El uso de una expresión regular para extraer el Zip o el Estado de la Ciudad encontrar la correcta o si es un error hacer las dos cosas.tire de la lista de las calles de una fuente de datos Corregir la ciudad y el estado, y, a continuación, la dirección de la calle.Una vez que obtenga una Dirección válida de la línea 1, ciudad, estado, zip y, a continuación, puede supuestos en línea de la dirección 2..3

No sé qué tan FACTIBLE sería, pero no he visto mencionado, así que pensé que iba a ir por delante y sugieren que este:

Si usted está estrictamente en los estados unidos...obtener una enorme base de datos de todos los códigos postales, los estados, las ciudades y las calles.Ahora mira en su dirección.Usted puede validar lo que se encuentra por las pruebas de que si, por ejemplo, la ciudad se encontró que existe en el estado en que se encuentra, o mediante la comprobación de si la calle se encontró que existe en la ciudad en la que se encuentra.Si no, es probable que Juan no es para Juan de la calle, pero es el nombre del destinatario...Básicamente, obtener la mayor información puede y comprobar las direcciones en contra de ella.Un ejemplo extremo sería para obtener UNA LISTA DE TODAS LAS DIRECCIONES EN LOS estados unidos DE UNA y luego encontrar que uno tiene la mayor relevancia partido a cada una de sus direcciones...

Hay javascript puerto de perl Geo::StreetAddress::US paquete: https://github.com/hassansin/parse-address .Es basado en expresiones regulares y funciona bastante bien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top