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(). данные должны быть 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 (condcoms) также будет отправлено в этот метод, поэтому для <!--[if IE 9]>IE9-specific content<![endif]--> этот метод получит '[if IE 9]>IE9-specific content<![endif]'.

HTMLParser.handle_decl(decl)

Этот метод вызывается для обработки объявления HTML doctype (например, <!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
Вернуться на верх