Выделенный HTML для простого текста с использованием Python

Я пытаюсь преобразовать кусок текста HTML с помощью BeautifulSoup. Вот пример:

<div>
    <p>
        Some text
        <span>more text</span>
        even more text
    </p>
    <ul>
        <li>list item</li>
        <li>yet another list item</li>
    </ul>
</div>
<p>Some other text</p>
<ul>
    <li>list item</li>
    <li>yet another list item</li>
</ul>

Я попытался сделать что-то вроде:

def parse_text(contents_string)
    Newlines = re.compile(r'[\r\n]\s+')
    bs = BeautifulSoup.BeautifulSoup(contents_string, convertEntities=BeautifulSoup.BeautifulSoup.HTML_ENTITIES)
    txt = bs.getText('\n')
    return Newlines.sub('\n', txt)

... но таким образом мой элемент span всегда находится на новой строке. Это, конечно, простой пример. Есть ли способ получить текст на странице HTML так, как он будет отображаться в браузере (не требуются какие-либо правила CSS, только обычные элементы div, span, li и т.д.) В Python?

Ответ 1

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

import html2text
html = open("foobar.html").read()
print html2text.html2text(html)

Выводится:

Some text more text even more text

  * list item
  * yet another list item

Some other text

  * list item
  * yet another list item

Ответ 2

Я столкнулся с той же проблемой, пытаясь проанализировать отображаемый HTML. Похоже, что BS не является идеальным пакетом для этого. @Del дает большое решение html2text.

В вопросе различного SO: BeautifulSoup get_text не разделяет все теги и JavaScript @Helge упоминается с помощью nltk. К сожалению, nltk, похоже, прекращает этот метод.

Я попробовал оба html2text и nltk.clean_html и был удивлен результатами синхронизации, поэтому подумал, что они гарантировали ответ для потомков. Конечно, скорости сильно зависят от содержимого данных...

Ответ от @Helge (nltk).

import nltk

%timeit nltk.clean_html(html)
was returning 153 us per loop

Сработало очень хорошо, чтобы вернуть строку с отображаемым html. Этот модуль nltk был быстрее, чем html2text, хотя, возможно, html2text более надежный.

Ответ выше из @del

betterHTML = html.decode(errors='ignore')
%timeit html2text.html2text(betterHTML)
%3.09 ms per loop