简短版!
import re, html
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
no_tags = tag_re.sub('', user_input)
ready_for_web = html.escape(no_tags)
正则表达式来源:MarkupSafe。他们的版本还可以处理 HTML 实体,而这个快速版本不行。
为什么不能只删除标签并保留文本?
防止人们在文本中使用 <i>斜体</i>
这样的标签容易,但是使输入内容完全无害化又是另外一回事了。本页面上的大多数技术将保留未闭合的注释(<!--
)和非标签角括号(blah <<<><blah
)等。如果它们在未关闭的注释内部,则 HTMLParser 版本甚至可以保留完整的标记。
如果您的模板是{{ firstname }} {{ lastname }}
?firstname='<a'
和 lastname='href="http://evil.example/">'
将被本页中每个标签剥离器放过(除了@Medeiros!),因为它们本身不是完整的标签。单纯地剥离正常的HTML标签是不够的。
Django 的strip_tags
是本问题答案的改进版本(请参见下一标题),其提供以下警告:
绝对不保证生成的字符串是 HTML 安全的。因此,永远不要标记 strip_tags
调用的结果为安全的,例如使用 escape()
进行转义。
遵循他们的建议!
要使用 HTMLParser 剥离标签,您必须多次运行它。
绕过本问题的最佳答案非常简单。
看这个字符串(来源和讨论):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
第一次HTML解析器看到它时,无法识别
<img...>
为标签。它看起来有问题,因此HTML解析器不会将其删除。它只会取出
<!-- 注释 -->
,留下以下内容:
<img src=x onerror=alert(1);//>
该问题于2014年三月向Django项目披露。他们旧的strip_tags
本质上与此问题的最佳答案相同。他们的新版本基本上是在循环中运行它,直到再次运行不改变字符串为止:
# _strip_once runs HTMLParser once, pulling out just the text of all the nodes.
def strip_tags(value):
"""Returns the given HTML with all tags stripped."""
# Note: in typical case this loop executes _strip_once once. Loop condition
# is redundant, but helps to reduce number of executions of _strip_once.
while '<' in value and '>' in value:
new_value = _strip_once(value)
if len(new_value) >= len(value):
# _strip_once was not able to detect more tags
break
value = new_value
return value
当然,如果您始终转义
strip_tags()
的结果,则不会出现任何问题。
更新于2015年3月19日: 在1.4.20、1.6.11、1.7.7和1.8c1之前的Django版本中存在一个错误。这些版本可能会在strip_tags()函数中进入无限循环。修复版本如上所示。
更多详情请见此处.
好的东西可以复制或使用
我的示例代码不处理HTML实体 - Django和MarkupSafe打包版本可以处理。
我的示例代码摘自优秀的MarkupSafe库,用于防止跨站脚本攻击。它方便快捷(具有其本地Python版本的C加速)。它被包含在Google App Engine中,并被Jinja2(2.7及以上版本)、Mako、Pylons等使用。它在Django 1.7的模板中很容易使用。
Django的strip_tags和其他HTML实用程序来自最新版本非常好,但我发现它们比MarkupSafe不太方便。它们非常自包含,您可以从这个文件中复制您所需的内容。
如果您需要删除几乎所有标记,则Bleach库很好。您可以强制执行规则,例如“我的用户可以使事物成为斜体,但他们不能制作iframes。”
了解您的标记剥离器的属性!对其进行模糊测试!这是我用于为此答案进行研究的代码。
羞怯的说明——问题本身是关于打印到控制台的,但这是“Python从字符串中删除HTML”的顶级Google搜索结果,因此此答案99%涉及网络。
&
)是一个重要的考虑因素。你可以选择:1)删除它们和标记(通常不可取,因为它们等同于纯文本),2)保持它们不变(如果被剥离的文本将要回到HTML环境中,则是一种合适的解决方案),或 3)将它们解码为纯文本(如果被剥离的文本将要进入数据库或其他非HTML环境中,或者如果你的网页框架自动对文本进行HTML转义)。 - Søren Løvborg