2009-08-07 16 views
5

Mi empresa tiene un cliente que realiza un seguimiento de los precios de productos de diferentes compañías en diferentes ubicaciones. Esta información va a una base de datos.Algoritmos o patrones para leer texto

Estas compañías envían los precios por correo electrónico a nuestros clientes todos los días, y por supuesto, todos los correos electrónicos tienen un formato diferente. Es imposible que ninguna de las empresas cambie su formato; no lo harán.

Algunos parecen algo así como esto:

 
    This is example text that could be many lines long... 

    Location 1 
    Product 1  Product 2  Product 3 
    $20.99  $21.99  $33.79 

    Location 2 
    Product 1  Product 2  Product 3 
    $24.99  $22.88  $35.59 

otros buscan algo así como esto:

 
    PRODUCT       PRICE   +/- 
    ------------  -------- ------- 
    Location 1 
    1             2007.30 +048.20 
    2             2022.50 +048.20 

    Maybe some multiline text here about a holiday or something... 

    Location 2 
    1             2017.30 +048.20 
    2             2032.50 +048.20 

Actualmente contamos con programas de análisis individuales escritos para el formato de correo electrónico de cada empresa. Pero estos formatos cambian con bastante frecuencia. No podemos contar con que los precios estén en la misma fila o columna cada vez.

Es trivial para nosotros mirar los correos electrónicos y determinar qué precio va con qué producto y en qué ubicación. Pero no tanto por nuestro código. Así que estoy tratando de encontrar una solución más flexible y me gustaría recibir sus sugerencias sobre qué enfoques tomar. Estoy abierto a cualquier cosa, desde regex a redes neuronales. Aprenderé lo que necesito para que esto funcione, simplemente no sé lo que necesito aprender. ¿Es esto un problema de lex/análisis? ¿Más similar a OCR?

El código no tiene que resolver los formatos por sí mismo. Los correos electrónicos caen en algunos 'estilos' principales como los de arriba. Realmente necesitamos que el código sea lo suficientemente flexible como para que una nueva línea de productos o espacios en blanco o algo así no haga que el archivo no sea analizable.

Gracias por cualquier sugerencia sobre por dónde empezar.

+1

Sería útil ver cómo está analizando uno de estos formatos en este momento. Alguien podría ser capaz de tomar su código existente y señalar dónde se puede hacer más flexible. –

+0

El código actual es básicamente: si la empresa es company1, vaya a la tercera línea, lea los primeros 12 caracteres como producto, luego lea los caracteres 45-50 como precio. Luego vaya a la cuarta línea ... Es muy, muy difícil de codificar. –

+0

@Scott, Ok, si el espacio en blanco está separando los datos en columnas como lo describo en mi respuesta, podría usar secuencias de comandos cómodamente. – nik

Respuesta

7

Creo que este problema sería adecuado para el generador de analizador apropiado. Las expresiones regulares son demasiado difíciles de probar y depurar si salen mal. Sin embargo, buscaría un generador de analizadores que sea fácil de usar como si fuera parte de un lenguaje.

Para este tipo de tareas iría con pyparsing ya que tiene el poder de un analizador completo de lr pero sin una gramática difícil de definir y muy buenas funciones de ayuda. El código es fácil de leer también.

from pyparsing import * 

aaa =""" This is example text that could be many lines long... 
      another line 

    Location 1 
    Product 1  Product 2  Product 3 
    $20.99  $21.99  $33.79 

    stuff in here you want to ignore 

    Location 2 
    Product 1  Product 2  Product 3 
    $24.99  $22.88  $35.59 """ 

result = SkipTo("Location").suppress() \ 
# in place of "location" could be any type of match like a re. 
     + OneOrMore(Word(alphas) + Word(nums)) \ 
     + OneOrMore(Word(nums+"$.")) \ 

all_results = OneOrMore(Group(result)) 

parsed = all_results.parseString(aaa) 

for block in parsed: 
    print block 

Esto devuelve una lista de listas.

['Location', '1', 'Product', '1', 'Product', '2', 'Product', '3', '$20.99', '$21.99', '$33.79'] 
['Location', '2', 'Product', '1', 'Product', '2', 'Product', '3', '$24.99', '$22.88', '$35.59'] 

Puede agrupar las cosas como quiera, pero para simplificar, acabo de devolver las listas. El espacio en blanco se ignora por defecto, lo que hace las cosas mucho más simples.

No sé si hay equivalentes en otros idiomas.

0

Has dado dos ejemplos de patrones para archivos de texto.
Creo que estos pueden manejarse con secuencias de comandos.
Algo como: AWK, sed, grep con bash scripting.


Un patrón en la primera muestra,

  1. sección comienza con la palabra clave Location [Número]
    • segunda línea de sección ha columnas que describe nombres de productos
    • tercera línea de sección ha columnas con precios para los productos

Puede haber un número variable de productos por sección.
Puede haber un número variable de secciones por archivo.
Los productos y precios están siempre en sus líneas designadas de una sección.
La separación del espacio en blanco identifica la asociación de columnas (product,price).
El número de productos en una sección coincide con el número de precios en esa sección.


Los datos recopilados probablemente se asimilarían en una base de datos.

0

Lo único que sé que usaría aquí son las expresiones regulares. Tres o cuatro expresiones podrían conducir la lógica de análisis para cada formato de correo electrónico.

Tratando de escribir el motor de análisis más general que el que, creo, estaría bordeando la sobreprogramación.

+0

Gracias. En este momento estamos explorando porque es posible que el método más general triplique los ingresos, lo que cambia nuestra definición habitual de 'sobreprogramación'. :) Si tiene ideas sobre métodos más generales, aunque parezcan excesivos, agréguelos. –

Cuestiones relacionadas