> **Источник:** https://python-all.ru/3.1/library/html.parser.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 19.1. `html.parser` – Простой парсер HTML и XHTML

Этот модуль определяет класс [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser), который служит основой для разбора текстовых файлов в формате HTML (язык гипертекстовой разметки) и XHTML.

#### `class html.parser.HTMLParser`

Класс [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) создаётся без аргументов.

Экземпляр [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) получает HTML-данные и вызывает функции-обработчики при начале и конце тегов. Класс [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) предназначен для переопределения пользователем, чтобы реализовать нужное поведение.

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

Также определено исключение:

#### `exception html.parser.HTMLParseError`

Исключение, вызываемое классом

[`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser)

при возникновении ошибки во время разбора. Это исключение предоставляет три атрибута:

`msg`

– краткое сообщение с описанием ошибки,

`lineno`

– номер строки, на которой была обнаружена ошибочная конструкция, и

`offset`

– количество символов от начала строки до начала конструкции.

Экземпляры [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) имеют следующие методы:

#### `HTMLParser.reset()`

Сбрасывает экземпляр. Теряет все необработанные данные. Вызывается неявно при создании экземпляра.

#### `HTMLParser.feed(data)`

Передаёт парсеру некоторый текст. Текст обрабатывается по мере поступления полных элементов; неполные данные буферизуются до тех пор, пока не будут переданы новые данные или не будет вызван

[`close()`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser.close)

.

#### `HTMLParser.close()`

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

[`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser)

–

[`close()`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser.close)

.

#### `HTMLParser.getpos()`

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

#### `HTMLParser.get_starttag_text()`

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

#### `HTMLParser.handle_starttag(tag, attrs)`

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

Аргумент *tag* – это имя тега, приведённое к нижнему регистру. Аргумент *attrs* – это список пар `(name, value)`, содержащий атрибуты, найденные внутри угловых скобок `<>` тега. Имя *name* переводится в нижний регистр, кавычки в значении *value* удалены, а ссылки на символы и сущности заменены. Например, для тега `<A HREF="http://www.cwi.nl/">` этот метод будет вызван как `handle_starttag('a', [('href', 'http://www.cwi.nl/')])`.

Все ссылки на сущности из [`html.entities`](https://python-all.ru/3.1/library/html.entities.html#module-html.entities) заменяются в значениях атрибутов.

#### `HTMLParser.handle_startendtag(tag, attrs)`

Аналогично

[`handle_starttag()`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser.handle_starttag)

, но вызывается, когда парсер встречает пустой тег в стиле XHTML (

`<a .../>`

). Этот метод может быть переопределён подклассами, которым требуется эта конкретная лексическая информация; реализация по умолчанию просто вызывает

[`handle_starttag()`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser.handle_starttag)

и

[`handle_endtag()`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser.handle_endtag)

.

#### `HTMLParser.handle_endtag(tag)`

Этот метод вызывается для обработки закрывающего тега элемента. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает. Аргумент

*tag*

– это имя тега, приведённое к нижнему регистру.

#### `HTMLParser.handle_data(data)`

Этот метод вызывается для обработки произвольных данных. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает.

#### `HTMLParser.handle_charref(name)`

Этот метод вызывается для обработки символьной ссылки вида

`&#ref;`

. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает.

#### `HTMLParser.handle_entityref(name)`

Этот метод вызывается для обработки общей ссылки на сущность вида

`&name;`

, где

*name*

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

#### `HTMLParser.handle_comment(data)`

Этот метод вызывается при обнаружении комментария. Аргумент

*comment*

– это строка, содержащая текст между разделителями

`--`

и

`--`

, но не сами разделители. Например, комментарий

`<!--text-->`

вызовет этот метод с аргументом

`'text'`

. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает.

#### `HTMLParser.handle_decl(decl)`

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

`doctype`

. Параметр

*decl*

будет содержать полное содержимое объявления внутри разметки

`<!...>`

. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает.

#### `HTMLParser.unknown_decl(data)`

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

*data*

будет содержать полное содержимое объявления внутри разметки

`<!...>`

. Иногда полезно переопределить этот метод в производном классе; реализация базового класса вызывает

[`HTMLParseError`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParseError)

.

#### `HTMLParser.handle_pi(data)`

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

> **Примечание**
>
> Класс [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) использует синтаксические правила SGML для обработки инструкций. Инструкция обработки XHTML, использующая завершающий `'?'`, приведёт к включению `'?'` в *data*.

## 19.1.1. Пример приложения для разбора HTML

В качестве базового примера ниже представлен очень простой парсер HTML, который использует [`HTMLParser`](https://python-all.ru/3.1/library/html.parser.html#html.parser.HTMLParser) класс для вывода тегов по мере их обнаружения:

```python
>>> from html.parser import HTMLParser
>>>
>>> class MyHTMLParser(HTMLParser):
...     def handle_starttag(self, tag, attrs):
...         print("Encountered a {} start tag".format(tag))
...     def handle_endtag(self, tag):
...         print("Encountered a {} end tag".format(tag))
...
>>> page = """<html><h1>Title</h1><p>I'm a paragraph!</p></html>"""
>>>
>>> myparser = MyHTMLParser()
>>> myparser.feed(page)
Encountered a html start tag
Encountered a h1 start tag
Encountered a h1 end tag
Encountered a p start tag
Encountered a p end tag
Encountered a html end tag
```
