Question

J'utilise l'API Appengine de Google

from google.appengine.api import urlfetch

pour récupérer une page Web. Le résultat de

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

est une chaîne du contenu HTML (dans result.content). Le problème est que les données que je veux analyser ne sont pas vraiment au format HTML. Je ne pense donc pas que l’utilisation d’un analyseur HTML python fonctionne pour moi. Je dois analyser tout le texte brut dans le corps du document HTML. Le seul problème est que urlfetch renvoie une seule chaîne de l'intégralité du document HTML, supprimant ainsi toutes les lignes et les espaces.

MODIFIER: D'accord, j'ai essayé de chercher une URL différente et apparemment, urlfetch ne supprime pas les nouvelles lignes, c'est la page Web originale que j'essayais d'analyser qui servait le fichier HTML de cette façon ... END EDIT

Si le document ressemble à ceci:

<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 sera ceci, après que urlfetch le récupère:

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

L'utilisation d'un analyseur HTML ne m'aide pas avec les données entre les balises body. J'allais donc utiliser des expressions régulières pour analyser mes données, mais comme vous pouvez le voir, la dernière partie d'une ligne est combinée à la première partie de la ligne suivante, et je ne sais pas comment la scinder. J'ai essayé

result.content.split('\n')

et

result.content.split('\r')

mais la liste résultante ne comportait qu'un seul élément. Je ne vois aucune option dans la fonction urlfetch de Google pour ne pas supprimer les nouvelles lignes.

Avez-vous des idées pour analyser ces données? Peut-être dois-je aller le chercher différemment?

Merci d'avance!

Était-ce utile?

La solution

Je comprends que le format du document est celui que vous avez posté. Dans ce cas, je conviens qu'un analyseur tel que Beautiful Soup peut ne pas être une bonne solution.

Je suppose que vous obtenez déjà les données intéressantes (entre les balises BODY) avec une expression régulière comme

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

alors, cela devrait être aussi simple que:

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

(note: je n'ai pas comparé ce code avec des cas de limites, et je m'attends à ce qu'il échoue. Il n'est qu'ici pour montrer l'idée générique)

Autres conseils

La seule suggestion à laquelle je puisse penser est de l’analyser comme si elle avait des colonnes de largeur fixe. Les nouvelles lignes ne sont pas prises en compte pour HTML.

Si vous avez le contrôle des données source, placez-les dans un fichier texte plutôt que HTML.

Une fois que vous avez le corps du texte en une seule et longue chaîne, vous pouvez le séparer comme suit. Cela suppose que chaque enregistrement comporte 26 caractères.

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 compréhension en lecture est une chose souhaitable. J'ai manqué le point sur le fait que les lignes fonctionnent ensemble sans séparateur entre elles, ce qui serait un peu le but de tout cela, n'est-ce pas? Donc, tant pis, ma réponse, ce n'est pas vraiment pertinent.

Si vous savez que chaque ligne est composée de 5 colonnes séparées par des espaces, alors (une fois que vous aurez supprimé le code HTML), vous pourrez faire quelque chose comme (non testé):

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)

Bien sûr, vous pouvez modifier le caractère de division et le nombre de colonnes selon vos besoins (éventuellement en les transmettant à la fonction de générateur en tant que paramètres supplémentaires), et ajouter le traitement des erreurs, le cas échéant.

Autres suggestions pour fractionner la chaîne s en blocs de 26 caractères:

En tant que liste:

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

En tant que générateur:

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

Remplacez range () par xrange () dans Python 2.x si s est très long.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top