Разбор данных фиксированного формата, встроенных в HTML в python - PullRequest
0 голосов
/ 03 января 2009

Я использую API Google AppIgine

from google.appengine.api import urlfetch

для загрузки веб-страницы. Результат

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

- это строка содержимого html (в result.content). Проблема заключается в том, что данные, которые я хочу проанализировать, на самом деле не в форме HTML, поэтому я не думаю, что использование анализатора Python HTML будет работать для меня. Мне нужно проанализировать весь текст в теле HTML-документа. Единственная проблема заключается в том, что urlfetch возвращает одну строку всего HTML-документа, удаляя все новые строки и лишние пробелы.

EDIT: Хорошо, я попытался получить другой URL, и, очевидно, urlfetch не удаляет символы новой строки, это была оригинальная веб-страница, которую я пытался проанализировать, которая показала HTML-файл таким образом ... КОНЕЦ РЕДАКТИРОВАНИЯ

Если документ выглядит примерно так:

<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 будет таким после того, как urlfetch извлечет его:

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

Использование анализатора HTML не поможет мне с данными между тегами body, поэтому я собирался использовать регулярные выражения для анализа моих данных, но, как вы можете видеть, последняя часть одной строки объединяется с первой частью следующая строка, и я не знаю, как ее разбить. Я пытался

result.content.split('\n')

и

result.content.split('\r')

но полученный список был всего лишь 1 элементом. В функции Google urlfetch не отображаются параметры, позволяющие не удалять переводы строк.

Есть идеи, как я могу проанализировать эти данные? Может быть, мне нужно получить его по-другому?

Заранее спасибо!

Ответы [ 5 ]

2 голосов
/ 04 января 2009

Я понимаю, что формат документа тот, который вы опубликовали. В этом случае я согласен с тем, что такой синтаксический анализатор, как Beautiful Soup , не может быть хорошим решением.

Я предполагаю, что вы уже получаете интересные данные (между тегами BODY) с регулярным выражением, например

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

тогда это должно быть так же просто, как:

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

(примечание: я не проверял этот код на граничные случаи, и я ожидаю, что он потерпит неудачу. Он только здесь, чтобы показать общую идею)

2 голосов
/ 03 января 2009

Единственное предложение, которое я могу придумать, - это проанализировать его, как если бы оно имело столбцы фиксированной ширины. Новые строки не учитываются для HTML.

Если у вас есть контроль над исходными данными, поместите их в текстовый файл, а не в HTML.

1 голос
/ 04 января 2009

Если у вас есть основной текст в виде одной длинной строки, его можно разбить следующим образом. Это предполагает, что каждая запись состоит из 26 символов.

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
0 голосов
/ 28 января 2009

Дополнительные предложения по разбиению строки s на блоки из 26 символов:

В виде списка:

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

Как генератор:

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

Замените range() на xrange() в Python 2.x, если s очень длинный.

0 голосов
/ 04 января 2009

РЕДАКТИРОВАТЬ: понимание прочитанного является желательной вещью. Я пропустил немного о строках, которые не были разделены между собой, и в этом вся суть, не так ли? Так что, не обращайте внимания на мой ответ, на самом деле он не актуален.


Если вы знаете, что каждая строка представляет собой 5 столбцов, разделенных пробелами, то (как только вы удалите HTML), вы можете сделать что-то вроде (не проверено):

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)

Конечно, вы можете при необходимости изменить символ разделения и количество столбцов (возможно, даже передав их в функцию генератора в качестве дополнительных параметров), и добавить обработку ошибок, если необходимо.

...