我需要一种方法来剥离标签和解码HTML实体为纯文本。下面的解决方案是基于Eloff的答案(我不能使用,因为它剥离实体)。
import html.parser
class HTMLTextExtractor(html.parser.HTMLParser):
def __init__(self):
super(HTMLTextExtractor, self).__init__()
self.result = [ ]
def handle_data(self, d):
self.result.append(d)
def get_text(self):
return ''.join(self.result)
def html_to_text(html):
"""Converts HTML to plain text (stripping tags and converting entities).
>>> html_to_text('<a href="#">Demo<!--...--> <em>(¬ \u0394ημώ)</em></a>')
'Demo (\xac \u0394\u03b7\u03bc\u03ce)'
"Plain text" doesn't mean result can safely be used as-is in HTML.
>>> html_to_text('<script>alert("Hello");</script>')
'<script>alert("Hello");</script>'
Always use html.escape to sanitize text before using in an HTML context!
HTMLParser will do its best to make sense of invalid HTML.
>>> html_to_text('x < y < z <!--b')
'x < y < z '
Named entities are handled as per HTML 5.
>>> html_to_text('&nosuchentity; ' ')
"&nosuchentity; ' "
"""
s = HTMLTextExtractor()
s.feed(html)
return s.get_text()
快速测试:
html = '<a href="#">Demo <em>(¬ \u0394ημώ)</em></a>'
print(repr(html_to_text(html)))
结果:
'Demo (¬ Δημώ)'
安全提示:不要混淆HTML剥离(将HTML转换为纯文本)和HTML消毒(将纯文本转换为HTML)。这个答案将删除HTML并将实体解码为纯文本——这并不能使结果在HTML上下文中安全使用。
例子:& lt; script>警报(“Hello”);& lt; / script>将转换为<script>alert("Hello");</script>,这是100%正确的行为,但如果结果纯文本按原样插入到HTML页面中,显然是不够的。
这个规则并不难:任何时候你插入一个纯文本字符串到HTML输出,总是HTML转义它(使用HTML .escape(s)),即使你“知道”它不包含HTML(例如,因为你剥离了HTML内容)。
但是,OP询问是否将结果打印到控制台,在这种情况下不需要HTML转义。相反,你可能想要剥离ASCII控制字符,因为它们会触发不需要的行为(特别是在Unix系统上):
import re
text = html_to_text(untrusted_html_input)
clean_text = re.sub(r'[\0-\x1f\x7f]+', '', text)
# Alternatively, if you want to allow newlines:
# clean_text = re.sub(r'[\0-\x09\x0b-\x1f\x7f]+', '', text)
print(clean_text)