Domanda

Sto usando l'API dell'appengine di Google

from google.appengine.api import urlfetch

per recuperare una pagina web. Il risultato di

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

è una stringa del contenuto html (in result.content). Il problema è che i dati che voglio analizzare non sono realmente in formato HTML, quindi non penso che usare un parser HTML Python funzionerà per me. Ho bisogno di analizzare tutto il testo normale nel corpo del documento HTML. L'unico problema è che urlfetch restituisce una singola stringa dell'intero documento HTML, rimuovendo tutte le nuove righe e gli spazi extra.

Modifica Ok, ho provato a recuperare un URL diverso e apparentemente urlfetch non elimina le nuove righe, era la pagina web originale che stavo cercando di analizzare che serviva il file HTML in quel modo ... MODIFICA FINE

Se il documento è simile a questo:

<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 sarà questo, dopo che urlfetch lo recupera:

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

L'uso di un parser HTML non mi aiuterà con i dati tra i tag body, quindi avrei usato espressioni regolari per analizzare i miei dati, ma come puoi vedere l'ultima parte di una riga viene combinata con la prima parte di la riga successiva e non so come dividerlo. Ho provato

result.content.split('\n')

e

result.content.split('\r')

ma l'elenco risultante era tutto solo 1 elemento. Non vedo alcuna opzione nella funzione urlfetch di Google per non rimuovere le nuove righe.

Qualche idea su come posso analizzare questi dati? Forse dovrei prenderlo diversamente?

Grazie in anticipo!

È stato utile?

Soluzione

Comprendo che il formato del documento è quello che hai pubblicato. In tal caso, sono d'accordo che un parser come Beautiful Soup potrebbe non essere una buona soluzione.

Presumo che tu stia già ottenendo i dati interessanti (tra i tag BODY) con un'espressione regolare come

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

quindi, dovrebbe essere facile come:

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

(nota: non ho verificato questo codice rispetto ai casi limite e mi aspetto che fallisca. È solo qui per mostrare l'idea generica)

Altri suggerimenti

L'unico suggerimento che mi viene in mente è di analizzarlo come se avesse colonne a larghezza fissa. Le nuove righe non vengono prese in considerazione per HTML.

Se hai il controllo dei dati di origine, inseriscili in un file di testo anziché in HTML.

Una volta che hai il corpo del testo come una singola stringa lunga, puoi scomporlo come segue. Ciò presume che ogni record contenga 26 caratteri.

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

EDIT: la comprensione della lettura è una cosa desiderabile. Mi sono perso un po 'le linee che correvano insieme senza un separatore tra loro, che sarebbe un po' il punto di tutto questo, no? Quindi, non importa la mia risposta, in realtà non è pertinente.


Se sai che ogni riga è composta da 5 colonne separate da spazio, allora (una volta eliminato l'html) potresti fare qualcosa del genere (non testato):

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)

Ovviamente, puoi modificare il carattere diviso e il numero di colonne secondo necessità (eventualmente anche passandole nella funzione generatore come parametri aggiuntivi) e aggiungere la gestione degli errori come appropriato.

Ulteriori suggerimenti per dividere la stringa s in blocchi di 26 caratteri:

Come elenco:

>>> [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']

Come generatore:

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

Sostituisci range () con xrange () in Python 2.x se s è molto lungo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top