html.parser — Простой HTML и XHTML парсер

Исходный код: Lib/html/parser.py


Модуль определяет класс HTMLParser, который служит основой для парсинг текстовых файлов, отформатированных в HTML (HyperText Mark-up Language) и XHTML.

class html.parser.HTMLParser(*, convert_charrefs=True)

Создаёт сущность парсера, способного анализировать недопустимую разметку.

Если convert_charrefs имеет значение True (по умолчанию), все ссылки на символ (за исключением ссылок в элементах script/style) автоматически преобразуются в соответствующие символы Юникода.

HTMLParser сущность питается данные о HTML и называет методы обработчика, когда начало помечает, конечные тэги, текст, комментарии, и с другими элементами повышения сталкиваются. Пользователь должен подкласс HTMLParser и отвергать его методы, чтобы осуществить желаемое поведение.

Парсер не проверяет, что тэги начала матча конечных тэгов или вызывают обработчика конечного тэга для элементов, которые закрыты неявно, закрыв внешний элемент.

Изменено в версии 3.4: convert_charrefs ключевой добавлен аргумент.

Изменено в версии 3.5: Дефолтом значение для аргумента convert_charrefs является теперь True.

Пример приложения синтаксического анализатора HTML

Как основной пример, ниже простой HTML парсер, который использует класс HTMLParser, чтобы распечатать тэги начала, конечные тэги и данные, поскольку с ними сталкиваются:

from html.parser import HTMLParser

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print("Encountered a start tag:", tag)

    def handle_endtag(self, tag):
        print("Encountered an end tag :", tag)

    def handle_data(self, data):
        print("Encountered some data  :", data)

parser = MyHTMLParser()
parser.feed('<html><head><title>Test</title></head>'
            '<body><h1>Parse me!</h1></body></html>')

Вывод будет следующим:

Encountered a start tag: html
Encountered a start tag: head
Encountered a start tag: title
Encountered some data  : Test
Encountered an end tag : title
Encountered an end tag : head
Encountered a start tag: body
Encountered a start tag: h1
Encountered some data  : Parse me!
Encountered an end tag : h1
Encountered an end tag : body
Encountered an end tag : html

Методы HTMLParser

HTMLParser сущности имеют следующие методы:

HTMLParser.feed(data)

Передать текст парсеру. Он обрабатывается в той мере, в какой состоит из полных элементов; неполные данные буферизованы, пока больше данных не питается, или close() называют. data должен быть str.

HTMLParser.close()

Принудительная обработка всех буферизованных данных, как если бы за ними следовала отметка конца файла. Этот метод может быть пересмотрен производным классом, чтобы определить дополнительную обработку в конце входа, но пересмотренная версия должна всегда называть метод базового класса HTMLParser close().

HTMLParser.reset()

Перезагрузка сущность. Теряет все необработанные данные. Вызывается неявно во время создания экземпляра.

HTMLParser.getpos()

Возвращает номер текущей строки и смещения.

HTMLParser.get_starttag_text()

Возвращает текст последнего открытого начального тега. Обычно это не требуется для структурированной обработки, но может быть полезно при работе с HTML «как развернутым» или для повторной генерации входных данных с минимальными изменениями (пробел между атрибуты может быть сохранен и т.д.).

Следующие методы вызываются при обнаружении данных или элементов разметки и предназначены для переопределения в подкласс. Реализации базового класса ничего не делают (кроме handle_startendtag()):

HTMLParser.handle_starttag(tag, attrs)

Этот метод вызывается для обработки начала тега (например, <div id="main">).

Аргумент tag является именем тега, преобразованного в нижний регистр. Аргумент attrs представляет собой список пар (name, value), содержащих атрибуты, найденные в <> скобках тега. name будет переведено в нижний регистр, и кавычки в value будут удалены, а ссылки на символ и сущности будут заменены.

Для сущность, для тега <A HREF="https://www.cwi.nl/">, этот метод будет вызван как handle_starttag('a', [('href', 'https://www.cwi.nl/')]).

Все ссылки на объекты из html.entities заменяются в атрибут значения.

HTMLParser.handle_endtag(tag)

Этот метод вызывается для обработки конечной метки элемента (например, </div>).

Аргумент tag является именем тега, преобразованного в нижний регистр.

HTMLParser.handle_startendtag(tag, attrs)

Аналогично handle_starttag(), но вызывается, когда парсер встречает пустой тег в стиле XHTML (<img ... />). Этот способ может быть переопределен подклассы, которые требуют этой конкретной лексической информации; реализация по умолчанию просто вызывает handle_starttag() и handle_endtag().

HTMLParser.handle_data(data)

Этот метод вызывается для обработки произвольных данных (например, текстовых узлов и содержимого <script>...</script> и <style>...</style>).

HTMLParser.handle_entityref(name)

Этот метод называют, чтобы обработать названную ссылку символ формы &name; (например, &gt;), где name - общая ссылка сущности (например, 'gt'). Этот метод никогда не вызывается, если convert_charrefs является True.

HTMLParser.handle_charref(name)

Этот метод называют, чтобы обработать десятичные и шестнадцатеричные числовые ссылки символ формы &#NNN; и &#xNNN;. Например, десятичный эквивалент для &gt; равен &#62;, в то время как шестнадцатеричный - &#x3E;; в этом случае метод будет принимать '62' или 'x3E'. Этот метод никогда не вызывается, если convert_charrefs является True.

HTMLParser.handle_comment(data)

Этот метод вызывается при обнаружении комментария (например, <!--comment-->).

Например, комментарий <!-- comment --> вызовет этот метод с аргументом ' comment '.

Содержимое условных комментариев (кондкомов) Internet Explorer также будет отправлено этому методу, поэтому, для <!--[if IE 9]>IE9-specific content<![endif]-->, этот метод получит '[if IE 9]>IE9-specific content<![endif]'.

HTMLParser.handle_decl(decl)

Этот метод вызывается для обработки объявления типа документа HTML (например, <!DOCTYPE html>).

Параметр decl будет представлять собой все содержимое объявления внутри разметки <!...> (например, 'DOCTYPE html').

HTMLParser.handle_pi(data)

Метод, вызываемый при обнаружении команды обработки. Параметр data будет содержать всю инструкцию по обработке. Например, для команды обработки <?proc color='red'> этот метод будет вызван как handle_pi("proc color='red'"). Она должна быть переопределена производным классом; реализация базового класса ничего не делает.

Примечание

Класс HTMLParser использует синтаксические правила SGML для обработки инструкций. Команда обработки XHTML с использованием конечного '?' приведет к включению '?' в data.

HTMLParser.unknown_decl(data)

Этот метод вызывается, когда парсер считывает нераспознанное объявление.

Параметр data будет представлять собой все содержимое объявления внутри разметки <![...]>. Иногда полезно переопределить производным классом. Реализация базового класса ничего не делает.

Примеры

Следующий класс реализует парсер, который будет используемый для иллюстрации дополнительных примеров:

from html.parser import HTMLParser
from html.entities import name2codepoint

class MyHTMLParser(HTMLParser):
    def handle_starttag(self, tag, attrs):
        print("Start tag:", tag)
        for attr in attrs:
            print("     attr:", attr)

    def handle_endtag(self, tag):
        print("End tag  :", tag)

    def handle_data(self, data):
        print("Data     :", data)

    def handle_comment(self, data):
        print("Comment  :", data)

    def handle_entityref(self, name):
        c = chr(name2codepoint[name])
        print("Named ent:", c)

    def handle_charref(self, name):
        if name.startswith('x'):
            c = chr(int(name[1:], 16))
        else:
            c = chr(int(name))
        print("Num ent  :", c)

    def handle_decl(self, data):
        print("Decl     :", data)

parser = MyHTMLParser()

Парсинг doctype:

>>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
...             '"http://www.w3.org/TR/html4/strict.dtd">')
Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"

Разбор элемента с несколькими атрибуты и заголовком:

>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')
Start tag: img
     attr: ('src', 'python-logo.png')
     attr: ('alt', 'The Python logo')
>>>
>>> parser.feed('<h1>Python</h1>')
Start tag: h1
Data     : Python
End tag  : h1

Содержание script и элементов style - возвращенный, как, без далее парсинг:

>>> parser.feed('<style type="text/css">#python { color: green }</style>')
Start tag: style
     attr: ('type', 'text/css')
Data     : #python { color: green }
End tag  : style

>>> parser.feed('<script type="text/javascript">'
...             'alert("<strong>hello!</strong>");</script>')
Start tag: script
     attr: ('type', 'text/javascript')
Data     : alert("<strong>hello!</strong>");
End tag  : script

Парсинг комментариев:

>>> parser.feed('<!-- a comment -->'
...             '<!--[if IE 9]>IE-specific content<![endif]-->')
Comment  :  a comment
Comment  : [if IE 9]>IE-specific content<![endif]

Названный парсинг и числовые ссылки символ и преобразование их к правильной случайной работе (примечание: эти 3 ссылки - весь эквивалент '>'):

>>> parser.feed('&gt;&#62;&#x3E;')
Named ent: >
Num ent  : >
Num ent  : >

Кормление неполного чанки к работам feed(), но handle_data() можно было бы назвать несколько раз (если convert_charrefs не установлен в True):

>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:
...     parser.feed(chunk)
...
Start tag: span
Data     : buff
Data     : ered
Data     : text
End tag  : span

Парсинг недействительного HTML (например атрибуты без кавычек) также работает:

>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')
Start tag: p
Start tag: a
     attr: ('class', 'link')
     attr: ('href', '#main')
Data     : tag soup
End tag  : p
End tag  : a