from mechanize import Browser
br = Browser()
br.open('http://somewebpage')
html = br.response().readlines()
for line in html:
print line
Lors de l'impression d'une ligne dans un fichier HTML, j'essaie de trouver un moyen d'afficher uniquement le contenu de chaque élément HTML et non la mise en forme elle-même. S'il le trouve '<a href="whatever.com">some text</a>'
, il n'imprimera que «du texte», '<b>hello</b>'
affichera «bonjour», etc. Comment procéder?
&
). Vous pouvez soit 1) les supprimer avec les balises (souvent indésirables et inutiles car elles sont équivalentes à du texte brut), 2) les laisser inchangées (une solution appropriée si le texte supprimé revient directement dans un contexte HTML) ou 3 ) les décoder en texte brut (si le texte supprimé va dans une base de données ou un autre contexte non HTML, ou si votre infrastructure Web effectue automatiquement l'échappement HTML du texte pour vous).Réponses:
J'ai toujours utilisé cette fonction pour supprimer les balises HTML, car elle ne nécessite que le stdlib Python:
Pour Python 3:
Pour Python 2:
la source
&
) ainsi que les balises.__init__
fonction de la classe parent . Voir ici: stackoverflow.com/questions/11061058/… .parser = HTMLParser()
ethtml = parser.unescape(html)
au début de la fonction strip_tags.Je n'ai pas beaucoup réfléchi aux cas qui vont manquer, mais vous pouvez faire un regex simple:
Pour ceux qui ne comprennent pas l'expression régulière, cela recherche une chaîne
<...>
, où le contenu interne est composé d'un ou plusieurs caractères (+
) qui ne sont pas un<
. Les?
moyens qu'il correspondra à la plus petite chaîne qu'il peut trouver. Par exemple<p>Hello</p>
, il correspondra<'p>
et</p>
séparément avec le?
. Sans cela, il correspondra à la chaîne entière<..Hello..>
.Si une non-balise
<
apparaît en html (par exemple.2 < 3
), Elle doit de toute façon être écrite sous forme de séquence d'échappement&...
afin que cela^<
ne soit pas nécessaire.la source
&
) inchangées dans la sortie.cgi.escape(s, True)
), même si vous "savez" qu'elle ne contient pas de HTML (par exemple parce que vous avez supprimé le contenu HTML) . Cependant, ce n'est pas ce que OP a demandé.Vous pouvez utiliser la
get_text()
fonction BeautifulSoup .Il est conseillé de spécifier explicitement l' analyseur , par exemple as
BeautifulSoup(html_str, features="html.parser")
, pour que la sortie soit reproductible.la source
Version courte!
Source d'expression régulière: MarkupSafe . Leur version gère également les entités HTML, contrairement à celle rapide.
Pourquoi ne puis-je pas simplement retirer les étiquettes et les laisser?
C'est une chose de garder les gens à l'
<i>italicizing</i>
écart des choses, sans laisseri
s flotter. Mais c'est une autre chose de prendre des entrées arbitraires et de les rendre complètement inoffensives. La plupart des techniques de cette page laisseront intacts des éléments comme les commentaires non fermés (<!--
) et les crochets qui ne font pas partie des balises (blah <<<><blah
). La version HTMLParser peut même laisser des balises complètes, si elles se trouvent dans un commentaire non fermé.Et si votre modèle l'est
{{ firstname }} {{ lastname }}
?firstname = '<a'
etlastname = 'href="http://evil.com/">'
seront laissés passer par tous les décapants de balises sur cette page (sauf @Medeiros!), car ce ne sont pas des balises complètes par eux-mêmes. Il ne suffit pas de supprimer les balises HTML normales.Django's
strip_tags
, une version améliorée (voir le titre suivant) de la réponse la plus importante à cette question, donne l'avertissement suivant:Suivez leurs conseils!
Pour supprimer les balises avec HTMLParser, vous devez l'exécuter plusieurs fois.
Il est facile de contourner la première réponse à cette question.
Regardez cette chaîne ( source et discussion ):
La première fois que HTMLParser le voit, il ne peut pas dire qu'il
<img...>
s'agit d'une balise. Il a l'air cassé, donc HTMLParser ne s'en débarrasse pas. Il enlève seulement le<!-- comments -->
, vous laissant avecCe problème a été divulgué au projet Django en mars 2014. Leur ancien
strip_tags
était essentiellement le même que la première réponse à cette question. Leur nouvelle version l' exécute essentiellement en boucle jusqu'à ce que la relancer ne change pas la chaîne:Bien sûr, rien de tout cela n'est un problème si vous échappez toujours au résultat de
strip_tags()
.Mise à jour 19 mars 2015 : il y avait un bogue dans les versions de Django avant 1.4.20, 1.6.11, 1.7.7 et 1.8c1. Ces versions pourraient entrer dans une boucle infinie dans la fonction strip_tags (). La version fixe est reproduite ci-dessus. Plus de détails ici .
Bonnes choses à copier ou à utiliser
Mon exemple de code ne gère pas les entités HTML - les versions packagées Django et MarkupSafe le font.
Mon exemple de code est tiré de l'excellente bibliothèque MarkupSafe pour la prévention des scripts intersites . C'est pratique et rapide (avec des accélérations C vers sa version native Python). Il est inclus dans Google App Engine et utilisé par Jinja2 (2.7 et plus) , Mako, Pylons, etc. Il fonctionne facilement avec les modèles Django de Django 1.7.
Les strip_tags de Django et les autres utilitaires html d'une version récente sont bons, mais je les trouve moins pratiques que MarkupSafe. Ils sont assez autonomes, vous pouvez copier ce dont vous avez besoin à partir de ce fichier .
Si vous devez supprimer presque toutes les balises, la bibliothèque Bleach est bonne. Vous pouvez lui faire appliquer des règles telles que «mes utilisateurs peuvent mettre les choses en italique, mais ils ne peuvent pas créer d'iframes».
Comprenez les propriétés de votre strip-teaseuse! Exécutez des tests fuzz dessus! Voici le code que j'ai utilisé pour faire la recherche de cette réponse.
note penaude - La question elle-même concerne l'impression sur la console, mais c'est le meilleur résultat Google pour "python strip html from string", c'est pourquoi cette réponse est à 99% sur le Web.
la source
J'avais besoin d'un moyen de supprimer les balises et de décoder les entités HTML en texte brut. La solution suivante est basée sur la réponse d'Eloff (que je ne pouvais pas utiliser car elle dépouille les entités).
Un test rapide:
Résultat:
La gestion des erreurs:
&#apos;
, qui sont valides en XML et XHTML, mais pas en HTML simple) provoqueront uneValueError
exception.ValueError
exception.Note de sécurité: ne confondez pas le dépouillement HTML (conversion de HTML en texte brut) avec la désinfection HTML (conversion de texte brut en HTML). Cette réponse supprimera le HTML et décodera les entités en texte brut - ce qui ne rend pas le résultat sûr à utiliser dans un contexte HTML.
Exemple:
<script>alert("Hello");</script>
sera converti en<script>alert("Hello");</script>
, ce qui est un comportement correct à 100%, mais évidemment insuffisant si le texte brut résultant est inséré tel quel dans une page HTML.La règle n'est pas difficile: chaque fois que vous insérez une chaîne de texte en clair dans la sortie HTML, vous devez toujours y échapper (en utilisant
cgi.escape(s, True)
), même si vous "savez" qu'elle ne contient pas de HTML (par exemple parce que vous avez supprimé le contenu HTML) .(Cependant, l'OP a demandé comment imprimer le résultat sur la console, auquel cas aucun échappement HTML n'est nécessaire.)
Version Python 3.4+: (avec doctest!)
Notez que HTMLParser s'est amélioré en Python 3 (ce qui signifie moins de code et une meilleure gestion des erreurs).
la source
Il existe un moyen simple pour cela:
L'idée est expliquée ici: http://youtu.be/2tu9LTDujbw
Vous pouvez le voir fonctionner ici: http://youtu.be/HPkNPcYed9M?t=35s
PS - Si vous êtes intéressé par la classe (sur le débogage intelligent avec python) je vous donne un lien: http://www.udacity.com/overview/Course/cs259/CourseRev/1 . C'est gratuit!
Vous êtes les bienvenus! :)
la source
<b class="o'>x</b>
comme sorties des fonctions d'entréex
. Mais en réalité, cette entrée n'est pas valide. Je pense que c'est pourquoi les gens préfèrent les bibliothèques.Si vous avez besoin de conserver des entités HTML (ie
&
), j'ai ajouté la méthode "handle_entityref" à la réponse d' Eloff .la source
Si vous souhaitez supprimer toutes les balises HTML, la méthode la plus simple que j'ai trouvée consiste à utiliser BeautifulSoup:
J'ai essayé le code de la réponse acceptée mais j'obtenais "RuntimeError: la profondeur de récursivité maximale dépassée", ce qui ne s'est pas produit avec le bloc de code ci-dessus.
la source
''.join(BeautifulSoup('<em>he</em>llo<br>world').find_all(text=True))
. Ici, la sortie est "helloworld", alors que vous voulez probablement que ce soit "hello world".' '.join(BeautifulSoup('<em>he</em>llo<br>world').find_all(text=True))
n'aide pas car il devient "he llo world".Voici une solution simple qui supprime les balises HTML et décode les entités HTML basées sur la
lxml
bibliothèque incroyablement rapide :la source
text_content()
revientlxml.etree._ElementUnicodeResult
donc vous devrez peut-être le lancer en chaîne d'abordstr
pour les opérations de chaîne comme l'+
indexation[]
. Ajout d'un casting pour faire bonne mesure de toute façon.Une solution basée sur lxml.html (lxml est une bibliothèque native et donc beaucoup plus rapide que toute solution python pure).
Si vous avez besoin de plus de contrôle sur ce qui est purifié avant de le convertir en texte, vous pouvez utiliser explicitement le nettoyeur lxml en passant les options souhaitées dans le constructeur, par exemple:
la source
Le package Beautiful Soup le fait immédiatement pour vous.
la source
Voici ma solution pour python 3.
Je ne sais pas si c'est parfait, mais j'ai résolu mon cas d'utilisation et cela semble simple.
la source
Vous pouvez utiliser un analyseur HTML différent ( comme lxml ou Beautiful Soup ) - celui qui offre des fonctions pour extraire uniquement du texte. Ou, vous pouvez exécuter une expression régulière sur votre chaîne de ligne qui supprime les balises. Voir les documents Python pour plus.
la source
lxml.html.fromstring(s).text_content()
&
) en texte.J'ai utilisé la réponse d'Eloff avec succès pour Python 3.1 [merci beaucoup!].
J'ai effectué une mise à niveau vers Python 3.2.3 et j'ai rencontré des erreurs.
La solution, fournie ici grâce au répondeur Thomas K, est d'insérer
super().__init__()
dans le code suivant:... pour que ça ressemble à ceci:
... et cela fonctionnera pour Python 3.2.3.
Encore une fois, merci à Thomas K pour le correctif et pour le code original d'Eloff fournis ci-dessus!
la source
Vous pouvez écrire votre propre fonction:
la source
Les solutions avec HTML-Parser sont toutes cassables, si elles ne s'exécutent qu'une seule fois:
résulte en:
ce que vous avez l'intention d'empêcher. si vous utilisez un analyseur HTML, comptez les balises jusqu'à ce que zéro soit remplacé:
la source
html_to_text
et que vous incorporez le texte en sortie de cette fonction dans html sans échapper à ce texte, c'est le manque d'échappement, qui est une vulnérabilité de sécurité, pas lahtml_to_text
fonction. Lahtml_to_text
fonction ne vous a jamais promis que la sortie serait du texte. Et l'insertion de texte en html sans s'échapper est une vulnérabilité de sécurité potentielle, que vous ayez obtenu le textehtml_to_text
ou une autre source.C'est une solution rapide et peut être encore plus optimisée, mais cela fonctionnera bien. Ce code remplacera toutes les balises non vides par "" et supprime toutes les balises html d'un texte d'entrée donné. Vous pouvez l'exécuter à l'aide de la sortie d'entrée ./file.py
la source
Une adaptation en python 3 de la réponse de Søren-Løvborg
la source
Pour un projet, j'avais besoin de strip HTML, mais aussi css et js. Ainsi, j'ai fait une variation de la réponse d'Eloffs:
la source
Voici une solution similaire à la réponse actuellement acceptée ( https://stackoverflow.com/a/925630/95989 ), sauf qu'elle utilise
HTMLParser
directement la classe interne (c.-à-d. Pas de sous-classement), la rendant ainsi beaucoup plus concise:la source
J'analyse les fichiers Lisezmoi de Github et je trouve que ce qui suit fonctionne vraiment bien:
Puis
Supprime tous les démarques et html correctement.
la source
En utilisant BeautifulSoup, html2text ou le code de @Eloff, la plupart du temps, il reste des éléments html, du code javascript ...
Vous pouvez donc utiliser une combinaison de ces bibliothèques et supprimer le formatage de démarque (Python 3):
Cela fonctionne bien pour moi, mais il peut être amélioré, bien sûr ...
la source
Code simple!. Cela supprimera toutes sortes de balises et de contenu à l'intérieur.
Mais cela ne donnera pas le résultat complet si le texte contient des symboles <> à l' intérieur.
la source
la source
Cette méthode fonctionne parfaitement pour moi et ne nécessite aucune installation supplémentaire:
la source