如何用Python检测字符串是否包含HTML代码?
如何判断一个字符串里是否包含HTML内容(可以是HTML4、HTML5,或者只是文本中的部分HTML)?我不需要知道HTML的版本,只想知道这个字符串是纯文本还是包含HTML。通常,文本是多行的,还可能有空行。
更新:
示例输入:
包含HTML的:
<head><title>I'm title</title></head>
Hello, <b>world</b>
不包含HTML的:
<ht fldf d><
<html><head> head <body></body> html
6 个回答
检查是否有结束标签。我觉得这是最简单也是最可靠的方法。
"</html>" in possibly_html
如果有结束的HTML标签,那么它看起来就像是HTML,否则就不太像了。
如果你只想知道一个字符串里是否包含HTML文本,那么这里有一个没提到的简单方法,就是用一个正则表达式,像下面这样:
</?\s*[a-z-][^>]*\s*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);)
需要注意的是,虽然这个方法比用HTML解析器要快很多,但根据你期待的HTML标记的复杂程度,它可能会不太准确。
这里有一个测试,可以让你大概了解这个正则表达式的适用范围。
你可以很简单地扩展内置的 HTMLParser,这个工具已经可以处理解析工作,并且可以收集(开始/结束)标签
、属性
和数据
。为了确认文档是否有效,开始标签的数量应该和结束标签的数量相匹配:
from html.parser import HTMLParser
class MyHTMLParser(HTMLParser):
def __init__(self):
super().__init__()
self.start_tags = list()
self.end_tags = list()
self.attributes = list()
def is_text_html(self):
return len(self.start_tags) == len(self.end_tags)
def handle_starttag(self, tag, attrs):
self.start_tags.append(tag)
self.attributes.append(attrs)
def handle_endtag(self, tag):
self.end_tags.append(tag)
def handle_data(self, data):
print("Encountered some data :", data)
然后
>>> parser = MyHTMLParser()
>>> parser.feed("<head><title>I'm title</title></head>"
"Hello, <b>world</b>")
>>> parser.is_text_html()
True
>>> parser.feed("<ht fldf d><"
"<html><head> head <body></body> html")
>>> parser.is_text_html()
False
我想到的一种方法是,通过尝试把文本当作HTML来解析,找到开始标签和结束标签,然后把这些标签和一组已知的可接受的HTML元素进行交集。
举个例子:
#!/usr/bin/env python
from __future__ import print_function
from HTMLParser import HTMLParser
from html5lib.sanitizer import HTMLSanitizerMixin
class TestHTMLParser(HTMLParser):
def __init__(self, *args, **kwargs):
HTMLParser.__init__(self, *args, **kwargs)
self.elements = set()
def handle_starttag(self, tag, attrs):
self.elements.add(tag)
def handle_endtag(self, tag):
self.elements.add(tag)
def is_html(text):
elements = set(HTMLSanitizerMixin.acceptable_elements)
parser = TestHTMLParser()
parser.feed(text)
return True if parser.elements.intersection(elements) else False
print(is_html("foo bar"))
print(is_html("<p>Hello World!</p>"))
print(is_html("<html><head><title>Title</title></head><body><p>Hello!</p></body></html>")) # noqa
输出结果:
$ python foo.py
False
True
True
这个方法适用于包含部分HTML元素的文本。
注意:这个方法使用了 html5lib,所以可能不适用于其他类型的文档,但这个技巧可以很容易地进行调整。
你可以使用一个叫做 BeautifulSoup
的HTML解析器。这个工具非常努力地去解析HTML,即使是那些有点问题的HTML,它的宽容程度会根据所用的底层解析器而有所不同。
>>> from bs4 import BeautifulSoup
>>> html = """<html>
... <head><title>I'm title</title></head>
... </html>"""
>>> non_html = "This is not an html"
>>> bool(BeautifulSoup(html, "html.parser").find())
True
>>> bool(BeautifulSoup(non_html, "html.parser").find())
False
这个基本上是尝试在字符串中找到任何HTML元素。如果找到了,结果就是 True
。
这里有一个关于HTML片段的另一个例子:
>>> html = "Hello, <b>world</b>"
>>> bool(BeautifulSoup(html, "html.parser").find())
True
另外,你也可以使用 lxml.html
:
>>> import lxml.html
>>> html = 'Hello, <b>world</b>'
>>> non_html = "<ht fldf d><"
>>> lxml.html.fromstring(html).find('.//*') is not None
True
>>> lxml.html.fromstring(non_html).find('.//*') is not None
False