web-dev-qa-db-fra.com

Échapper aux caractères HTML spéciaux en Python

J'ai une chaîne où des caractères spéciaux tels que ' ou " ou & (...) peuvent apparaître. Dans la ficelle:

string = """ Hello "XYZ" this 'is' a test & so on """

comment puis-je échapper automatiquement à chaque caractère spécial, de sorte que je reçois ceci:

string = " Hello "XYZ" this 'is' a test & so on "
21
creativz

Dans Python 3.2, vous pourriez utiliser la fonction html.escape , par exemple.

>>> string = """ Hello "XYZ" this 'is' a test & so on """
>>> import html
>>> html.escape(string)
' Hello "XYZ" this 'is' a test & so on '

Pour les versions antérieures de Python, consultez http://wiki.python.org/moin/EscapingHtml :

Le module cgi fourni avec Python a une fonction escape() :

import cgi

s = cgi.escape( """& < >""" )   # s = "&amp; &lt; &gt;"

Cependant, il n'échappe pas aux caractères au-delà de &, < et >. S'il est utilisé en tant que cgi.escape(string_to_escape, quote=True), il échappe également à ".


Voici un petit extrait qui vous permettra d'échapper aux citations et aux apostrophes:

 html_escape_table = {
     "&": "&amp;",
     '"': "&quot;",
     "'": "&apos;",
     ">": "&gt;",
     "<": "&lt;",
     }

 def html_escape(text):
     """Produce entities within text."""
     return "".join(html_escape_table.get(c,c) for c in text)

Vous pouvez également utiliser escape() &AGRAVE; PARTIR DE xml.sax.saxutils pour sortir du code HTML. Cette fonction devrait s'exécuter plus rapidement. La fonction unescape() du même module peut recevoir les mêmes arguments pour décoder une chaîne.

from xml.sax.saxutils import escape, unescape
# escape() and unescape() takes care of &, < and >.
html_escape_table = {
    '"': "&quot;",
    "'": "&apos;"
}
html_unescape_table = {v:k for k, v in html_escape_table.items()}

def html_escape(text):
    return escape(text, html_escape_table)

def html_unescape(text):
    return unescape(text, html_unescape_table)
35
kennytm

La méthode cgi.escape convertira les caractères spéciaux en balises HTML valides

 import cgi
 original_string = 'Hello "XYZ" this \'is\' a test & so on '
 escaped_string = cgi.escape(original_string, True)
 print original_string
 print escaped_string

aura pour résultat

Hello "XYZ" this 'is' a test & so on 
Hello &quot;XYZ&quot; this 'is' a test &amp; so on 

Le second paramètre optionnel sur cgi.escape échappe aux guillemets. Par défaut, ils ne sont pas échappés

5
Robert Christie

Une simple fonction de chaîne le fera:

def escape(t):
    """HTML-escape the text in `t`."""
    return (t
        .replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
        .replace("'", "&#39;").replace('"', "&quot;")
        )

D'autres réponses dans cette discussion ont des problèmes mineurs: La méthode cgi.escape ignore pour une raison quelconque les guillemets simples et vous devez lui demander explicitement de faire les guillemets doubles. La page wiki liée effectue les cinq tâches mais utilise l'entité XML &apos;, qui n'est pas une entité HTML.

Cette fonction de code effectue les cinq tâches en tout temps, en utilisant des entités au format HTML.

4
Ned Batchelder

Les autres réponses ici aideront avec les personnages que vous avez énumérés et quelques autres. Toutefois, si vous souhaitez également convertir tout le reste en noms d'entités, vous devrez faire autre chose. Par exemple, si á doit être converti en &aacute;, ni cgi.escape ni html.escape ne vous y aideront. Vous voudrez faire quelque chose comme ceci qui utilise html.entities.entitydefs, qui est juste un dictionnaire. (Le code suivant est fait pour Python 3.x, mais il y a une tentative partielle de le rendre compatible avec 2.x pour vous donner une idée):

# -*- coding: utf-8 -*-

import sys

if sys.version_info[0]>2:
    from html.entities import entitydefs
else:
    from htmlentitydefs import entitydefs

text=";\"áèïøæỳ" #This is your string variable containing the stuff you want to convert
text=text.replace(";", "$ஸ$") #$ஸ$ is just something random the user isn't likely to have in the document. We're converting it so it doesn't convert the semi-colons in the entity name into entity names.
text=text.replace("$ஸ$", "&semi;") #Converting semi-colons to entity names

if sys.version_info[0]>2: #Using appropriate code for each Python version.
    for k,v in entitydefs.items():
        if k not in {"semi", "amp"}:
            text=text.replace(v, "&"+k+";") #You have to add the & and ; manually.
else:
    for k,v in entitydefs.iteritems():
        if k not in {"semi", "amp"}:
            text=text.replace(v, "&"+k+";") #You have to add the & and ; manually.

#The above code doesn't cover every single entity name, although I believe it covers everything in the Latin-1 character set. So, I'm manually doing some common ones I like hereafter:
text=text.replace("ŷ", "&ycirc;")
text=text.replace("Ŷ", "&Ycirc;")
text=text.replace("ŵ", "&wcirc;")
text=text.replace("Ŵ", "&Wcirc;")
text=text.replace("ỳ", "&#7923;")
text=text.replace("Ỳ", "&#7922;")
text=text.replace("ẃ", "&wacute;")
text=text.replace("Ẃ", "&Wacute;")
text=text.replace("ẁ", "&#7809;")
text=text.replace("Ẁ", "&#7808;")

print(text)
#Python 3.x outputs: &semi;&quot;&aacute;&egrave;&iuml;&oslash;&aelig;&#7923;
#The Python 2.x version outputs the wrong stuff. So, clearly you'll have to adjust the code somehow for it.
0
Shule