Pergunta

Eu estou usando api appengine do Google

from google.appengine.api import urlfetch

para buscar uma página web. O resultado da

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

é uma seqüência do conteúdo html (em result.content). O problema é que os dados que eu quero parse não é realmente em forma HTML, então eu não acho que usando um analisador HTML python vai funcionar para mim. Eu preciso analisar todo o texto simples no corpo do documento html. O único problema é que urlfetch retorna uma única seqüência de todo o documento HTML, removendo todas as novas linhas e espaços extras.

EDIT: Ok, eu tentei buscar uma URL diferente e aparentemente urlfetch não tira as novas linhas, foi o site original que eu estava tentando análise que serviu o arquivo HTML que maneira ... END EDIT

Se o documento é algo como isto:

<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á este, depois de urlfetch busca-lo:

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

Usando um analisador de HTML não irá me ajudar com os dados entre as tags body, então eu ia usar expresions regulares para analisar meus dados, mas como você pode ver a última parte de uma linha fica combinado com a primeira parte do a próxima linha, e eu não sei como dividi-lo. Tentei

result.content.split('\n')

e

result.content.split('\r')

mas a lista resultante era tudo apenas um elemento. Eu não vejo quaisquer opções em função urlfetch do google para não remover novas linhas.

Alguma idéia de como posso analisar esses dados? Talvez eu precise buscá-la de forma diferente?

Agradecemos antecipadamente!

Foi útil?

Solução

Eu entendo que o formato do documento é o que você postou. Nesse caso, concordo que um analisador como Beautiful Soup pode não ser uma boa solução.

Eu assumo que você já está recebendo os dados interessantes (entre as tags body) com uma expressão regular como

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

então, ele deve ser tão 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:. Eu não verificar este código contra os casos de fronteira, e eu espero que ele falhe É somente aqui para mostrar a ideia genérico)

Outras dicas

A única sugestão que eu posso pensar é analisá-lo como se fixou largura colunas. Novas linhas não são levados em consideração para HTML.

Se você tem o controle dos dados de origem, colocá-lo em um arquivo de texto em vez de HTML.

Depois de ter o corpo de texto como uma única seqüência, longo, você pode quebrá-lo da seguinte forma. Isso pressupõe que cada registro é de 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

EDIT: Compreensão de leitura é uma coisa desejável. Eu perdi o pouco sobre as linhas que está sendo executado em conjunto com nenhum separador entre eles, o que meio que seja o ponto de todo isso, não é? Então, deixa pra lá minha resposta, não é realmente relevante.


Se você sabe que cada linha é de 5 colunas separados por espaços, em seguida, (uma vez que você retirados do html), você poderia fazer algo assim (não testado):

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)

Claro, você pode mudar o caráter dividido e número de colunas, conforme necessário (possivelmente até mesmo passá-los para a função de gerador como parâmetros adicionais), e adicionar manipulação de erro, conforme apropriado.

Outras sugestões para a divisão do s corda em blocos de 26 caracteres:

Como uma 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 um gerador:

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

Substituir range() com xrange() em Python 2.x se s é muito longo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top