如何用python检测字符串是不是包含html代码?
Posted
技术标签:
【中文标题】如何用python检测字符串是不是包含html代码?【英文标题】:How to detect with python if the string contains html code?如何用python检测字符串是否包含html代码? 【发布时间】:2014-09-11 10:09:46 【问题描述】:如何检测字符串是否包含 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
【问题讨论】:
为什么需要知道?你打算做什么不同的事情? 只检测字符串是否包含html,然后删除字符串或打印出来 【参考方案1】:您可以使用 HTML 解析器,例如 BeautifulSoup
。请注意,它确实尽最大努力解析 HTML,甚至是损坏的 HTML,它可能非常宽松,也可能不是非常宽松,具体取决于 underlying parser:
>>> 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
【讨论】:
non-html = "<html><head> head <body></body> html"
bool(BeautifulSoup(non_html, "html.parser").find()) => True
怎么样?它不是 html sn-p
即使non_html = "<html head> head <body jdkjs /body> html dkslfjglangaiowmgiowe"
也会通过测试:(
@static 好吧,这将是 True
,因为 BeautifulSoup
会尽力解析 html 并保持宽松。它会将其转换为<html><head> head <body></body> html</head></html>
。
很好,它通过了许多有问题的案例,但看起来,它通过了太多:non_html = "<ht fldf d><"
也可以工作
@static 是的,在这种情况下,它认为fldf
和d
是属性,而ht
标签只是没有关闭。很好的例子,谢谢:)【参考方案2】:
我想到的一种方法是通过尝试将文本解析为 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,因此它可能不一定适用于其他文档类型,但该技术可以轻松适应。
【讨论】:
它与你的解决方案基本相同——只是一个不同的库并使用已知元素的集合交集:P 我在 html5lib 中找不到HTMLSanitizerMixin
。【参考方案3】:
您可以轻松扩展已处理解析的内置HTMLParser,并收集(开始/结束)tags
、attrs
和data
。要断言文档是否有效,开始标签的数量应该与结束标签的数量相匹配:
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
【讨论】:
【参考方案4】:如果您只需要知道字符串是否包含 html 文本,那么此处未列出的另一种解决方案是使用如下的正则表达式:
</?\s*[a-z-][^>]*\s*>|(\&(?:[\w\d]+|#\d+|#x[a-f\d]+);)
请记住,虽然这比使用 HTML 解析器要快得多,但根据您所期望的 html 标记的复杂性,它可能会不准确。
Here is a test 了解上述正则表达式的一般概念。
【讨论】:
【参考方案5】:检查结束标签。我相信这是最简单和最强大的。
"</html>" in possibly_html
如果有一个结束的html标签,那么它看起来像html,否则没有那么多。
【讨论】:
这是一个很好的答案,假设输入是一个完整的 HTML 页面(其中包含</html>
。它不适用于部分 HTML(如 <b>some word</b>
)。
这个方法可以扩展为搜索任何html结束标签,比如b。正则表达式可能会使其更快,但基本原理保持不变。
因为你不知道文本中有哪些潜在的 HTML 标记,所以这种技术不能很好地工作:/【参考方案6】:
扩展上一篇文章我会做这样的事情来快速简单:
import sys, os
if os.path.exists("file.html"):
checkfile=open("file.html", mode="r", encoding="utf-8")
ishtml = False
for line in checkfile:
line=line.strip()
if line == "</html>"
ishtml = True
if ishtml:
print("This is an html file")
else:
print("This is not an html file")
【讨论】:
partials 和非样式化的 html 怎么样(即以上是关于如何用python检测字符串是不是包含html代码?的主要内容,如果未能解决你的问题,请参考以下文章