精简版!
import re, cgi
tag_re = re.compile(r'(<!--.*?-->|<[^>]*>)')
# Remove well-formed tags, fixing mistakes by legitimate users
no_tags = tag_re.sub('', user_input)
# Clean up anything else by escaping
ready_for_web = cgi.escape(no_tags)
正则表达式来源:MarkupSafe。它们的版本也可以处理HTML实体,而这一版本却不能。
为什么我不能只剥离标签并留下标签?
让人们远离<i>italicizing</i>
事物,而又不让事物i
浮起是一回事。但是,接受任意输入并使其完全无害是另一回事。此页面上的大多数技术都会保留未封闭的注释(<!--
)和不属于标签(blah <<<><blah
)的尖括号等内容。如果HTMLParser版本在未封闭的注释中,则它们甚至可以保留完整的标签。
如果您的模板是{{ firstname }} {{ lastname }}
什么? firstname = '<a'
并lastname = 'href="http://evil.com/">'
会被此页面上的每个标记剥离器(@Medeiros!除外)允许通过,因为它们本身并不是完整的标记。剥离普通的HTML标签是不够的。
Django的strip_tags
最佳答案的改进版本(请参见下一标题),给出以下警告:
绝对不能保证结果字符串是HTML安全的。因此,切勿在strip_tags
未先转义的情况下将通话结果标记为安全,例如使用escape()
。
遵循他们的建议!
要使用HTMLParser剥离标签,您必须多次运行它。
绕开这个问题的最佳答案很容易。
查看以下字符串(来源和讨论):
<img<!-- --> src=x onerror=alert(1);//><!-- -->
HTMLParser第一次看到它时,无法分辨出<img...>
是标签。它看起来很残破,因此HTMLParser不会摆脱它。它只取出<!-- comments -->
,让您
<img src=x onerror=alert(1);//>
该问题已在2014年3月的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打包版本可以处理HTML实体。
我的示例代码是从出色的MarkupSafe库中提取的,以防止跨站点脚本编写。它既方便又快速(C加速到其本机Python版本)。它包含在Google App Engine中,并由Jinja2(2.7及更高版本),Mako,Pylons等使用。它可以轻松地与Django 1.7中的Django模板一起使用。
Django的strip_tags和最新版本的其他html实用程序都不错,但是我发现它们不如MarkupSafe方便。它们非常独立,您可以从此文件中复制所需内容。
如果您需要剥离几乎所有标签,则Bleach库很好。您可以让它强制执行诸如“我的用户可以将其斜体显示,但他们不能创建iframe”之类的规则。
了解标签剥离器的属性!对它进行模糊测试! 这是我用来对此答案进行研究的代码。
令人毛骨悚然的注释 -问题本身是关于打印到控制台的问题,但这是Google针对“从字符串中提取python剥离html”的最高结果,所以这就是为什么网上答案是99%。
&
)。您可以1)连同标签一起删除它们(通常是不希望的,并且不必要,因为它们等效于纯文本),2)保留它们不变(如果剥离的文本直接回到HTML上下文,这是一个合适的解决方案)或3 )将其解码为纯文本(如果剥离的文本进入数据库或其他非HTML上下文,或者您的网络框架自动为您执行HTML文本转义)。