web-dev-qa-db-fra.com

Quel est le moyen le plus simple d'échapper à HTML en Python?

cgi.escape semble être un choix possible. Ça marche bien? Y at-il quelque chose qui est considéré comme meilleur?

131
Josh Gibson

cgi.escape c'est bien. Il échappe:

  • < à &lt;
  • > à &gt;
  • & à &amp;

Cela suffit pour tout le HTML.

EDIT: Si vous avez des caractères non-ASCII que vous voulez également échapper, pour les inclure dans un autre document encodé utilisant un encodage différent, comme , Craig dit: utilisation:

data.encode('ascii', 'xmlcharrefreplace')

N'oubliez pas de décoder data en unicode en premier, en utilisant le codage utilisé.

Cependant, selon mon expérience, ce type d’encodage est inutile si vous travaillez avec unicode tout le temps depuis le début. Il suffit d’encoder à la fin le codage spécifié dans l’en-tête du document (utf-8 pour une compatibilité maximale).

Exemple:

>>> cgi.escape(u'<a>bá</a>').encode('ascii', 'xmlcharrefreplace')
'&lt;a&gt;b&#225;&lt;/a&gt;

A noter également (merci Greg), le paramètre supplémentaire quotecgi.escape prend. Avec il réglé sur True, cgi.escape _ échappe également aux caractères de guillemets doubles (") afin que vous puissiez utiliser la valeur résultante dans un attribut XML/HTML.

EDIT: Notez que cgi.escape est déconseillé dans Python 3.2 en faveur de html.escape , qui fait la même chose sauf que quote est défini par défaut sur True.

174
nosklo

Dans Python 3.2), un nouveau module html a été introduit, utilisé pour échapper les caractères réservés du balisage HTML.

Il a une fonction escape():

>>> import html
>>> html.escape('x > 2 && x < 7')
'x &gt; 2 &amp;&amp; x &lt; 7'
93
Maciej Ziarko

Si vous souhaitez échapper du HTML dans une URL:

Ce n'est probablement pas ce que l'OP voulait (la question n'indique pas clairement dans quel contexte l'échappement doit être utilisé), mais la bibliothèque native de Python rllib dispose d'une méthode pour échapper aux entités HTML qui doivent être inclus dans une URL en toute sécurité.

Ce qui suit est un exemple:

#!/usr/bin/python
from urllib import quote

x = '+<>^&'
print quote(x) # prints '%2B%3C%3E%5E%26'

Trouvez les documents ici

10
SuperFamousGuy

Il y a aussi l'excellent paquetage markupsafe .

>>> from markupsafe import Markup, escape
>>> escape("<script>alert(document.cookie);</script>")
Markup(u'&lt;script&gt;alert(document.cookie);&lt;/script&gt;')

Le paquetage markupsafe est bien conçu et est probablement le moyen le plus polyvalent et le plus polyvalent pour s'échapper, IMHO, car:

  1. le retour (Markup) est une classe dérivée de Unicode (c'est-à-dire isinstance(escape('str'), unicode) == True
  2. il gère correctement l'entrée Unicode
  3. cela fonctionne dans Python (2.6, 2.7, 3.3 et pypy)
  4. il respecte les méthodes personnalisées des objets (c'est-à-dire des objets dotés d'une propriété __html__) et des surcharges de modèles (__html_format__).
8
Brian M. Hunt

cgi.escape devrait être utile pour échapper à HTML dans le sens limité d’échapper aux balises HTML et aux entités de caractères.

Cependant, vous devrez peut-être également prendre en compte les problèmes d'encodage: si le code HTML que vous souhaitez citer contient des caractères non-ASCII dans un encodage particulier, vous devez également veiller à les représenter de manière judicieuse lorsque vous citez. Peut-être que vous pourriez les convertir en entités. Sinon, vous devez vous assurer que les traductions de codage correctes sont effectuées entre le code HTML "source" et la page dans laquelle il est incorporé, afin d'éviter de corrompre les caractères non-ASCII.

8
Craig McQueen

Aucune bibliothèque, python pur, échappe en toute sécurité de texte en HTML:

text.replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;'
        ).encode('ascii', 'xmlcharrefreplace')
3
speedplane

Pas le moyen le plus simple, mais toujours simple. La principale différence avec le module cgi.escape - il fonctionnera toujours correctement si vous avez déjà &amp; dans votre texte. Comme vous pouvez le voir dans les commentaires:

cgi.escape version

def escape(s, quote=None):
    '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
    If the optional flag quote is true, the quotation mark character (")
is also translated.'''
    s = s.replace("&", "&amp;") # Must be done first!
    s = s.replace("<", "&lt;")
    s = s.replace(">", "&gt;")
    if quote:
        s = s.replace('"', "&quot;")
    return s

version regex

QUOTE_PATTERN = r"""([&<>"'])(?!(amp|lt|gt|quot|#39);)"""
def escape(Word):
    """
    Replaces special characters <>&"' to HTML-safe sequences. 
    With attention to already escaped characters.
    """
    replace_with = {
        '<': '&gt;',
        '>': '&lt;',
        '&': '&amp;',
        '"': '&quot;', # should be escaped in attributes
        "'": '&#39'    # should be escaped in attributes
    }
    quote_pattern = re.compile(QUOTE_PATTERN)
    return re.sub(quote_pattern, lambda x: replace_with[x.group(0)], Word)
2
palestamp

cgi.escape élargi

Cette version améliore cgi.escape. Il préserve également les espaces et les nouvelles lignes. Renvoie une chaîne unicode.

def escape_html(text):
    """escape strings for display in HTML"""
    return cgi.escape(text, quote=True).\
           replace(u'\n', u'<br />').\
           replace(u'\t', u'&emsp;').\
           replace(u'  ', u' &nbsp;')

par exemple

>>> escape_html('<foo>\nfoo\t"bar"')
u'&lt;foo&gt;<br />foo&emsp;&quot;bar&quot;'
2
JamesThomasMoon1979

Via BeautifulSoup4 :

>>> bs4.dammit import EntitySubstitution
>>> esub = EntitySubstitution()
>>> esub.substitute_html("r&d")
'r&amp;d'
0
scharfmn