web-dev-qa-db-fra.com

Rendu HTML en texte brut en utilisant Python

J'essaie de convertir un morceau de texte HTML avec BeautifulSoup. Voici un exemple:

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

J'ai essayé de faire quelque chose comme:

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)

... mais de cette façon, mon élément span est toujours sur une nouvelle ligne. Ceci est bien sûr un exemple simple. Existe-t-il un moyen d'obtenir le texte dans la page HTML comme la façon dont il sera rendu dans le navigateur (aucune règle CSS n'est requise, juste la façon habituelle de rendre les éléments div, span, li, etc.) en Python?

36
btatarov

BeautifulSoup est une bibliothèque de scraping, donc ce n'est probablement pas le meilleur choix pour faire un rendu HTML. S'il n'est pas essentiel d'utiliser BeautifulSoup, jetez un œil à html2text . Par exemple:

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

Cela produit:

 Un texte plus de texte encore plus de texte 
 
 * Élément de liste 
 * Encore un autre élément de liste 
 
 Un autre texte 
 
 * élément de liste 
 * encore un autre élément de liste 
82
del

Je rencontrais le même problème en essayant d'analyser le HTML rendu. Fondamentalement, il semble que BS ne soit pas le package idéal pour cela. @Del donne la grande solution html2text.

Sur un différet SO question: BeautifulSoup get_text ne supprime pas toutes les balises et JavaScript @Helge mentionné en utilisant nltk. Malheureusement, nltk semble abandonner cette méthode.

J'ai essayé à la fois html2text et nltk.clean_html et j'ai été surpris par les résultats du timing, alors j'ai pensé qu'ils méritaient une réponse pour la postérité. Bien sûr, les vitesses dépendent fortement du contenu des données ...

Réponse de @Helge (nltk).

import nltk

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

Cela a très bien fonctionné pour renvoyer une chaîne avec du HTML rendu. Ce module nltk était plus rapide que même html2text, bien que peut-être html2text soit plus robuste.

Réponse ci-dessus de @del

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