Как определить с помощью 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, как BeautifulSoup, Обратите внимание, что он действительно старается проанализировать 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

Один из способов, о котором я подумал, - это пересечь найденные начальные и конечные теги, пытаясь проанализировать текст как 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.

NB. При этом используется html5lib, поэтому он может не работать для других типов документов, но метод может быть легко адаптирован.

Вы можете легко расширить встроенный 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

Проверьте наличие конечных тегов. Это самый простой и самый надежный, я верю.

"</html>" in possibly_html

Если есть конечный HTML-тег, то он выглядит как HTML, иначе не так много.

Если все, что вам нужно знать, это то, содержит ли строка html-текст или нет, тогда другим решением, не указанным здесь, будет использование выражения регулярного выражения, подобного следующему:

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

Имейте в виду, что, хотя это будет гораздо более быстрое решение, чем использование парсера HTML, оно может быть потенциально неточным в зависимости от сложности разметки html, которую вы ожидаете.

Вот тест приведенного выше регулярного выражения для общего представления о его покрытии.

Продолжая предыдущий пост, я бы сделал что-то подобное для чего-то быстрого и простого:

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")
Другие вопросы по тегам