208 votes

Code Python pour supprimer les balises HTML d'une chaîne de caractères

J'ai un texte comme celui-ci :

text = """<div>
<h1>Title</h1>
<p>A long text........ </p>
<a href=""> a link </a>
</div>"""

en utilisant du Python pur, sans module externe, je veux avoir ceci :

>>> print remove_tags(text)
Title A long text..... a link

Je sais que je peux le faire en utilisant lxml.html.fromstring(text).text_content() mais j'ai besoin de réaliser la même chose en Python pur en utilisant la bibliothèque intégrée ou std pour 2.6+.

Comment puis-je faire ça ?

2 votes

Y a-t-il une raison spécifique pour laquelle vous ne voulez pas utiliser un module externe ?

1 votes

Pas de permissions pour installer des modules sur le serveur...

428voto

c24b Points 98

Utilisation d'une regex

En utilisant une regex, vous pouvez nettoyer tout ce qui se trouve à l'intérieur. <> :

import re
# as per recommendation from @freylis, compile once only
CLEANR = re.compile('<.*?>') 

def cleanhtml(raw_html):
  cleantext = re.sub(CLEANR, '', raw_html)
  return cleantext

Certains textes HTML peuvent également contenir des entités qui ne sont pas entre parenthèses, telles que ' &nsbm '. Si c'est le cas, vous pouvez écrire la regex comme suit

CLEANR = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});')

Ce site lien contient plus de détails à ce sujet.

Utilisation de BeautifulSoup

Vous pouvez également utiliser BeautifulSoup paquet supplémentaire pour découvrir tout le texte brut.

Vous devez définir explicitement un analyseur syntaxique lorsque vous appelez BeautifulSoup. Je recommande "lxml" comme mentionné dans les réponses alternatives (beaucoup plus robuste que celle par défaut ( html.parser ) (c'est-à-dire disponible sans installation supplémentaire).

from bs4 import BeautifulSoup
cleantext = BeautifulSoup(raw_html, "lxml").text

Mais cela ne vous empêche pas d'utiliser des bibliothèques externes, je recommande donc la première solution.

EDIT : Pour utiliser lxml vous devez pip install lxml .

50voto

lvc Points 12046

Python intègre plusieurs modules XML. Le plus simple pour le cas où vous avez déjà une chaîne de caractères avec le HTML complet est le suivant xml.etree qui fonctionne (un peu) de la même manière que l'exemple lxml que vous mentionnez :

def remove_tags(text):
    return ''.join(xml.etree.ElementTree.fromstring(text).itertext())

3 votes

Cela a fonctionné pour moi mais faites attention aux balises html du type autoclose. Example : </br>J'ai eu un "ParseError : mismatched tag : line 1, column 9" car cette balise est fermée sans être ouverte auparavant. C'est la même chose pour toutes les balises html autocloses.

40voto

Amber Points 159296

Notez que ce n'est pas parfait, car si vous aviez quelque chose comme, disons, <a title=">"> il se briserait. Cependant, c'est à peu près ce que vous obtiendrez de plus proche en Python non-bibliothèque sans une fonction vraiment complexe :

import re

TAG_RE = re.compile(r'<[^>]+>')

def remove_tags(text):
    return TAG_RE.sub('', text)

Cependant, comme le mentionne lvc xml.etree est disponible dans la bibliothèque standard de Python, de sorte que vous pouvez probablement l'adapter pour qu'il serve comme votre système existant lxml version :

def remove_tags(text):
    return ''.join(xml.etree.ElementTree.fromstring(text).itertext())

9voto

Medeiros Points 725

Il existe un moyen simple de le faire dans tout langage de type C. Le style n'est pas pythonique mais fonctionne avec du Python pur :

def remove_html_markup(s):
    tag = False
    quote = False
    out = ""

    for c in s:
            if c == '<' and not quote:
                tag = True
            elif c == '>' and not quote:
                tag = False
            elif (c == '"' or c == "'") and tag:
                quote = not quote
            elif not tag:
                out = out + c

    return out

L'idée est basée sur une simple machine à états finis et est expliquée en détail ici : http://youtu.be/2tu9LTDujbw

Vous pouvez le voir fonctionner ici : http://youtu.be/HPkNPcYed9M?t=35s

PS - Si vous êtes intéressé par le cours (sur le débogage intelligent avec python) je vous donne un lien : https://www.udacity.com/course/software-debugging--cs259 . C'est gratuit !

-13voto

user1899895 Points 1
global temp

temp =''

s = ' '

def remove_strings(text):

    global temp 

    if text == '':

        return temp

    start = text.find('<')

    end = text.find('>')

    if start == -1 and end == -1 :

        temp = temp + text

    return temp

newstring = text[end+1:]

fresh_start = newstring.find('<')

if newstring[:fresh_start] != '':

    temp += s+newstring[:fresh_start]

remove_strings(newstring[fresh_start:])

return temp

30 votes

Votre réponse est : a) terriblement formulée (viole pep8 par exemple), b) exagérée car il existe des outils pour faire la même chose, c) susceptible d'échouer (que se passe-t-il lorsque le html a le caractère > dans un des attributs ?), d) globale au XXIème siècle dans un cas aussi trivial ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X