【问题标题】: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,然后删除字符串或打印出来

标签: python html parsing detect


【解决方案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 = "&lt;html&gt;&lt;head&gt; head &lt;body&gt;&lt;/body&gt; html" bool(BeautifulSoup(non_html, "html.parser").find()) =&gt; True 怎么样?它不是 html sn-p
  • 即使non_html = "&lt;html head&gt; head &lt;body jdkjs /body&gt; html dkslfjglangaiowmgiowe" 也会通过测试:(
  • @static 好吧,这将是 True,因为 BeautifulSoup 会尽力解析 html 并保持宽松。它会将其转换为&lt;html&gt;&lt;head&gt; head &lt;body&gt;&lt;/body&gt; html&lt;/head&gt;&lt;/html&gt;。
  • 很好,它通过了许多有问题的案例,但看起来,它通过了太多:non_html = "&lt;ht fldf d&gt;&lt;" 也可以工作
  • @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 文本,那么此处未列出的另一种解决方案是使用如下的正则表达式:

    &lt;/?\s*[a-z-][^&gt;]*\s*&gt;|(\&amp;(?:[\w\d]+|#\d+|#x[a-f\d]+);)

    请记住,虽然这比使用 HTML 解析器要快得多,但根据您所期望的 html 标记的复杂性,它可能会不准确。

    Here is a test 了解上述正则表达式的一般概念。

    【讨论】:

      【解决方案5】:

      检查结束标签。我相信这是最简单和最强大的。

      "</html>" in possibly_html
      

      如果有一个结束的html标签,那么它看起来像html,否则没有那么多。

      【讨论】:

      • 这是一个很好的答案,假设输入是一个完整的 HTML 页面(其中包含 &lt;/html&gt;。它不适用于部分 HTML(如 &lt;b&gt;some word&lt;/b&gt;)。
      • 这个方法可以扩展为搜索任何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 怎么样(即
      猜你喜欢
      • 1970-01-01
      • 2016-12-25
      • 1970-01-01
      • 2015-09-08
      • 2015-10-12
      • 2014-10-05
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      相关资源
      最近更新 更多