2009-03-13 16 views
9

Tengo una clase de dirección que usa una expresión regular para analizar el número de la casa, el nombre de la calle y el tipo de calle desde la primera línea de una dirección. Este código generalmente funciona bien, pero estoy publicando aquí para compartir con la comunidad y para ver si alguien tiene sugerencias para mejorar.Expresión regular para analizar direcciones postales

Nota: Las constantes STREETTYPES y QUADRANT contienen todos los tipos de calle y cuadrantes relevantes, respectivamente.

He incluido un subconjunto aquí:

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, Cuadrante, StreetName y StreetType son todas las propiedades de la clase.

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; 
       } 
      } 
     } 

    } 
+1

Centrándose en la separación de la parte número de casa del resto, esto es demostrado (Direcciones alemanes) código de producción utilicé: '/ (. *) [\.] ((?: \ d {1,4} -)? \ d {1,4} (?: \ s? \ w)?) $/i' it captura "foostreet 42", "foost.14" (espacio omitido), "footst. 14-22" (intervall), "footstreet 14 A" (letra calificada/w o sin espacio antes), sin embargo, s resistente a la mayoría de otros insumos (es decir si es parcialmente datos heredados, con información en el lugar equivocado, etc.). –

Respuesta

6

no sé qué país que se encuentre, pero si usted está en los EE.UU. y quiere gastar algo de dinero en la validación de direcciones, se pueden comprar productos relacionados USPS here. Y here es un buen lugar para encontrar listas de palabras gratis del USPS para palabras y abreviaturas esperadas. Estoy seguro de que páginas similares están disponibles para otros países.

+0

Olvidé incluir esa estipulación ... tiene que ser gratis. :) –

+0

Además, sí, esto es solo para direcciones de Estados Unidos –

+2

Los enlaces en la respuesta ahora están rotos. Trabajo en la industria de verificación de direcciones con SmartyStreets. Querrá un proveedor certificado por CASS para verificar las direcciones (por ejemplo, le sugiero que busque "liveaddress api" en Google). – Matt

6

Creo que debe aclarar su situación de uso.

A menos que se encuentre en un escenario muy, muy limitado, donde las direcciones se ingresaron siguiendo un esquema estricto, analizar las direcciones de contenido es un problema extremadamente difícil de resolver y, por lo general, bastante inútil (a menos que sea el razón de ser de su aplicación).

Si está limitado a un país en particular que tiene convenciones muy específicas para escribir direcciones, entonces usar estas expresiones regulares podría obtener el 90% del camino.
Sin embargo, tan pronto como tenga que comenzar a aceptar direcciones en el extranjero, está jodido.
Incluso si es un sitio centrado en los EE. UU., Existe una buena posibilidad de que deba aceptar direcciones de ciudadanos estadounidenses que vivan en el extranjero, por ejemplo.

Nuevamente, puede estar bien en un campo muy limitado, pero casi siempre es una mala idea validar o dividir direcciones que no fueron estrictamente validadas y restringidas en el momento en que el usuario las ingresó.
Cuando hace cumplir algunas reglas estrictas para que los usuarios ingresen sus direcciones, estas terminan siendo inadecuadas en una pequeña porción de casos, incluso en los mejores componentes de validación de direcciones que existen.

sólo algunas cosas que estropear dirección de análisis:

  • códigos postales (códigos postales) en ocasiones se ubican antes, después, o incluso puede no existir en absoluto.
  • códigos postales siguen reglas estrictas: un código postal de 10 dígitos es probablemente fácil de identificar como no válido, pero ¿qué pasa con uno inexistente? ¿Qué hay de más códigos como los que se usan en el Reino Unido, por ejemplo?
  • ¿Qué tal un lugar como Hong Kong donde podrías escribir la dirección en inglés, chino tradicional o mandarín?
  • ¿Qué pasa si está perfectamente bien dividir su dirección y escribirla fuera de secuencia?
  • incluso si acaba de análisis sintáctico de EE.UU. direcciones, hay por lo menos un puñado de maneras de describir un apartado de correos: también puede utilizar Lista de Correos, entrega general y luego tienen que añadir un código de 4 dígitos al código postal, que normalmente probablemente no estar presente en todo ...

el fondo es

Si conseguir direcciones en un formato analizable es realmente importante, estar 100% seguro que pueda obtener todas las combinaciones posibles a la derecha o tendrá un porcentaje de fallas que significarán usuarios frustrados y pérdidas de ventas.
Si no tiene una cobertura del 100% del caso, entonces no aplique reglas estrictas para el usuario.
No puedo contar la cantidad de sitios web que dejé de comprar porque necesitarían un código postal/postal cuando el lugar en el que vivo no tiene ninguno.

Lo siento por la diatriba, pero yo creo que es importante que las personas que quieran hacer la validación de direcciones y el análisis pensar mucho acerca de lo que están consiguiendo ellos mismos en.

+0

Solo unas pocas notas: Esta aplicación es solo para ciudadanos de EE. UU. La ley prohíbe que la empresa trabaje con entidades extranjeras, por lo que no debería ser un problema. Además, esto es solo para analizar la primera línea de la dirección (por ejemplo, 12345 Main St). No estoy preocupado con el estado de la ciudad o el código postal. –

0

Me trataron de conseguir que esto funcione, pero parece como aunque tiene un miembro estático de una clase StreetTypes que no está incluido. Parece funcionar excepto eso, pero no puedo hacer muchas pruebas sin eso.

+0

Hay una constante STREETTYPE definida en la pregunta original. Usa eso. –

8

Diviértete con direcciones y expresiones regulares, te espera un viaje largo y horrible.

Estás tratando de poner orden en el caos.

Por cada "123 Simple Way", hay un "14 1/2 South".

Luego, para más risas, está Salt Lake City: "855 South 1300 East".

Diviértete con eso.

Existen más excepciones que reglas cuando se trata de direcciones de calles.

0

Estoy de acuerdo en que su rigurosidad va a ser un problema. Estoy escribiendo un analizador de direcciones diseñado para quitar direcciones de avisos clasificados donde el formato podría ser casi cualquier cosa. Por ejemplo, para tus partidos de cuadrante, estás ignorando la puntuación por completo. Tengo que buscar datos que podrían representar NE de todas estas maneras diferentes:

"NE", "NE", "NE", "NE", "N. E", "Nordeste", "Nordeste"

así que estoy usando la siguiente coincidencia de patrones que debe coger todos los calificadores de dirección no importa la forma en que se expresan:

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

por supuesto, el contexto también es importante, ya que "no" va a ser igualado por esto. Pero "NE" para Nebraska sería igualado por cualquiera de las dos opciones, por lo que debes tener cuidado con lo que está a la izquierda y a la derecha en tu expresión más amplia. Tengo que compilar listas de palabras que comúnmente aparecen intercaladas en textos de direcciones que no son componentes de direcciones, como "cerca, x-calle, adentro, a través", etc.

Es un problema muy difícil, y Estoy de acuerdo que Salt Lake City es una perra. Además de tener el formato de doble dirección/coordenadas, también lo componen al referirse a cosas como "3700 North 5300 East Arborville Way", donde las calles se pueden referenciar por nombre, número o ambos.

+0

Recuerde, este algoritmo es solo para hacer coincidir la parte de dirección de la dirección general (por ejemplo, 123 Simple Way) ... No me preocupan la ciudad, el estado o el código postal. –

2

Esto realmente funciona bastante bien, excepto que no saca números de apartamento. Estamos trabajando en eso. También tosió un poco cuando teníamos una dirección de 769 Branch Ave. Por supuesto, "rama" es uno de los tipos de calle que está buscando. Todo se remonta a ese orden del caos. Sabemos que se romperá aquí y allá.

+0

De acuerdo ... Sería imposible hacer algo a prueba de balas. –

Cuestiones relacionadas