Pregunta

Estoy usando la app de Google App

from google.appengine.api import urlfetch

para obtener una página web. El resultado de

result = urlfetch.fetch("http://www.example.com/index.html")

es una cadena del contenido html (en result.content). El problema es que los datos que quiero analizar no están realmente en formato HTML, por lo que no creo que usar un analizador HTML de Python funcione para mí. Necesito analizar todo el texto sin formato en el cuerpo del documento html. El único problema es que urlfetch devuelve una sola cadena de todo el documento HTML, eliminando todas las nuevas líneas y espacios adicionales.

EDITAR: De acuerdo, intenté obtener una URL diferente y, al parecer, urlfetch no elimina las nuevas líneas, fue la página web original que intenté analizar la que sirvió al archivo HTML de esa manera ... EDITAR FINAL

Si el documento es algo como esto:

<html><head></head><body>
AAA 123 888 2008-10-30 ABC
BBB 987 332 2009-01-02 JSE
...
A4A       288        AAA
</body></html>

result.content será esto, después de que urlfetch lo busque:

'<html><head></head><body>AAA 123 888 2008-10-30 ABCBBB 987     2009-01-02 JSE...A4A     288            AAA</body></html>'

El uso de un analizador HTML no me ayudará con los datos entre las etiquetas del cuerpo, por lo que iba a utilizar expresiones regulares para analizar mis datos, pero como puede ver, la última parte de una línea se combina con la primera parte de La siguiente línea, y no sé cómo dividirla. Lo intenté

result.content.split('\n')

y

result.content.split('\r')

pero la lista resultante era solo 1 elemento. No veo ninguna opción en la función urlfetch de Google para no eliminar nuevas líneas.

¿Alguna idea de cómo puedo analizar estos datos? Tal vez necesito buscarlo de manera diferente?

Gracias de antemano!

¿Fue útil?

Solución

Entiendo que el formato del documento es el que usted ha publicado. En ese caso, estoy de acuerdo en que un analizador como Beautiful Soup puede no ser una buena solución.

Supongo que ya está obteniendo los datos interesantes (entre las etiquetas BODY) con una expresión regular como

import re
data = re.findall('<body>([^\<]*)</body>', result)[0]

entonces, debería ser tan fácil como:

start = 0
end = 5
while (end<len(data)):
   print data[start:end]
   start = end+1
   end = end+5
print data[start:]

(nota: no verifiqué este código en los casos de límites y espero que falle. Solo está aquí para mostrar la idea genérica)

Otros consejos

La única sugerencia que se me ocurre es analizarla como si tuviera columnas de ancho fijo. Las nuevas líneas no se toman en consideración para HTML.

Si tiene el control de los datos de origen, póngalos en un archivo de texto en lugar de HTML.

Una vez que tenga el texto del cuerpo como una sola cadena larga, puede dividirlo de la siguiente manera. Esto supone que cada registro tiene 26 caracteres.

body= "AAA 123 888 2008-10-30 ABCBBB 987     2009-01-02 JSE...A4A     288            AAA"
for i in range(0,len(body),26):
    line= body[i:i+26]
    # parse the line

EDITAR: La comprensión de lectura es algo deseable. Me perdí la parte de las líneas que se ejecutan juntas sin ningún separador entre ellas, ¿cuál sería el punto central de esto, verdad? Entonces, no importa mi respuesta, no es realmente relevante.


Si sabe que cada línea tiene 5 columnas separadas por espacios, entonces (una vez que haya eliminado el html) podría hacer algo como (sin probar):

def generate_lines(datastring):
    while datastring:
        splitresult = datastring.split(' ', 5)
        if len(splitresult) >= 5:
            datastring = splitresult[5]
        else:
            datastring = None
        yield splitresult[:5]

for line in generate_lines(data):
    process_data_line(line)

Por supuesto, puede cambiar el carácter dividido y el número de columnas según sea necesario (posiblemente incluso pasarlas a la función del generador como parámetros adicionales), y agregar el manejo de errores según corresponda.

Otras sugerencias para dividir la cadena s en bloques de 26 caracteres:

Como una lista:

>>> [s[x:x+26] for x in range(0, len(s), 26)]
['AAA 123 888 2008-10-30 ABC',
 'BBB 987     2009-01-02 JSE',
 'A4A     288            AAA']

Como generador:

>>> for line in (s[x:x+26] for x in range(0, len(s), 26)): print line
AAA 123 888 2008-10-30 ABC
BBB 987     2009-01-02 JSE
A4A     288            AAA

Reemplace range () con xrange () en Python 2.x si s es muy largo.

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