在 Python 中转义 HTML 最简单的方法是什么?

逃避似乎是一个可能的选择。它工作得好吗? 有什么东西被认为是更好的吗?

149117 次浏览

现在正确的答案是 html.escape ,在 python 中,它在3.2之前是 cgi.escape:

  • <呼叫 &lt;
  • >呼叫 &gt;
  • &呼叫 &amp;

这对所有 HTML 来说都足够了。

编辑: 如果你有非 ascii 字符也想转义,为了包含在另一个使用不同编码的编码文档中,就像 克雷格说的那样,只需使用:

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

不要忘记首先将 data解码为 unicode,使用它被编码的任何编码。

然而,根据我的经验,如果您从一开始就一直使用 unicode,那么这种编码是无用的。只需在文档头中指定的编码的末尾进行编码(utf-8表示最大兼容性)。

例如:

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

同样值得注意的是(感谢 Greg)额外的 quote参数 cgi.escape。设置为 True后,cgi.escape还转义双引号字符(") ,因此可以在 XML/HTML 属性中使用结果值。

编辑: 请注意,在 Python 3.2中,cgi.escape 已被弃用,取而代之的是 html.escape,除了 quote默认为 True 之外,html.escape的功能与 cgi.escape 相同。

在转义 HTML 标记和字符实体的有限意义上,cgi.escape 应该能够很好地转义 HTML。

但是您可能还必须考虑编码问题: 如果您要引用的 HTML 在特定编码中具有非 ASCII 字符,那么您还必须注意在引用时合理地表示这些字符。也许你可以把它们转换成实体。否则,您应该确保在“源”HTML 和它所嵌入的页面之间进行正确的编码转换,以避免损坏非 ASCII 字符。

在 Python 3.2中引入了一个新的 html模块,它用于从 HTML 标记转义保留字符。

它只有一个功能 escape():

>>> import html
>>> html.escape('x > 2 && x < 7 single quote: \' double quote: "')
'x &gt; 2 &amp;&amp; x &lt; 7 single quote: &#x27; double quote: &quot;'

如果您希望在 URL 中转义 HTML:

这可能不是 OP 想要的(问题没有明确指出转义应该在哪个上下文中使用) ,但 Python 的本机库 Urllib有一个方法来转义需要安全地包含在 URL 中的 HTML 实体。

下面是一个例子:

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


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

在这里找医生

cgi.escape延长

此版本改进了 cgi.escape。它还保留了空格和换行符。返回一个 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;')

比如说

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

对于 Python 2.7中的遗留代码,可以通过 美味汤4完成:

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

虽然不容易,但还是很直接。与 CGI 逃跑模块的主要区别-它仍然会正常工作,如果你已经有 &amp;在你的文本。正如你从评论中看到的:

Cgi.escape 版本

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

正则表达式版本

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)

还有优秀的 Markupsafe 软件包

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

markupsafe软件包设计得很好,可能是最通用和 Python 化的逃逸方式,恕我直言,因为:

  1. Return (Markup)是从 unicode (即 isinstance(escape('str'), unicode) == True)派生的类
  2. 正确处理 Unicode 输入
  3. 它可以在 Python (2.6、2.7、3.3和 py)中工作
  4. 它尊重对象的自定义方法(即具有 __html__属性的对象)和模板重载(__html_format__)。

没有库,纯 Python,安全地将文本转换为 html 文本:

text.replace('&', '&amp;').replace('>', '&gt;').replace('<', '&lt;'
).replace('\'','&#39;').replace('"','&#34;').encode('ascii', 'xmlcharrefreplace')