J'ai un texte comme ça:
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 je dois atteindre le même résultat en pure Python en utilisant la bibliothèque intégrée ou std pour la version 2.6+.
Comment puis je faire ça?
En utilisant une regex, vous pouvez tout nettoyer à l'intérieur de <>
:
import re
def cleanhtml(raw_html):
cleanr = re.compile('<.*?>')
cleantext = re.sub(cleanr, '', raw_html)
return cleantext
Certains textes HTML peuvent également contenir des entités qui ne sont pas entre crochets, telles que '&nsbm
'. Si tel est le cas, vous pouvez écrire la regex sous la forme suivante:
cleanr = re.compile('<.*?>|&([a-z0-9]+|#[0-9]{1,6}|#x[0-9a-f]{1,6});')
Ce lien contient plus de détails à ce sujet.
Vous pouvez également utiliser BeautifulSoup
package supplémentaire pour trouver tout le texte brut
Vous aurez besoin de définir explicitement un analyseur lors de l'appel de BeautifulSoup. Je recommande "lxml" comme indiqué dans les réponses alternatives (beaucoup plus robuste que celui par défaut (c'est-à-dire disponible sans installation supplémentaire) "html.parser"
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.
Python a plusieurs modules XML intégrés. Le plus simple pour le cas où vous avez déjà une chaîne avec le code HTML complet est xml.etree
, ce qui fonctionne (un peu) de manière similaire à l'exemple lxml que vous avez mentionné :
_def remove_tags(text):
return ''.join(xml.etree.ElementTree.fromstring(text).itertext())
_
Notez que ce n’est pas parfait, car si vous aviez quelque chose comme, par exemple, _<a title=">">
_, cela casserait. Cependant, c'est à peu près tout ce que vous obtiendrez dans une non-bibliothèque Python 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 Python, de sorte que vous pourriez probablement l'adapter pour servir comme votre version existante lxml
:
_def remove_tags(text):
return ''.join(xml.etree.ElementTree.fromstring(text).itertext())
_
Il existe un moyen simple d’y parvenir dans n’importe quel langage semblable à C. Le style n'est pas Pythonic 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, basée sur une simple machine à états finis, est expliquée ici: http://youtu.be/2tu9LTDujbw
Vous pouvez le voir fonctionner ici: http://youtu.be/HPkNPcYed9M?t=35s
PS - Si la classe vous intéresse (sur le débogage intelligent avec Python), je vous donne un lien: http://www.udacity.com/overview/Course/cs259/CourseRev/1 . C'est gratuit!