Документация Python неофициальный перевод

html.parser.md

285 строк · 19.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.4/library/html.parser.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 20.2. [`html.parser`](https://python-all.ru/3.4/library/html.parser.html#module-html.parser) – Простой парсер HTML и XHTML89**Исходный код:** [Lib/html/parser.py](https://python-all.ru/src/3.4/Lib/html/parser.py)1011---1213Этот модуль определяет класс [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser), который служит основой для разбора текстовых файлов в формате HTML (язык гипертекстовой разметки) и XHTML.1415#### `class html.parser.HTMLParser(strict=False, *, convert_charrefs=False)`1617Создаёт экземпляр парсера.1819Если *convert\_charrefs* равен `True` (по умолчанию `False`), все символьные ссылки (кроме тех, что в элементах `script`/`style`) автоматически преобразуются в соответствующие символы Unicode. Использование `convert_charrefs=True` рекомендуется, и оно станет значением по умолчанию в Python 3.5.2021Если *strict* равен `False` (значение по умолчанию), парсер будет принимать и разбирать некорректную разметку. Если *strict* равен `True`, парсер возбудит исключение [`HTMLParseError`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParseError) вместо [\[1\]](https://python-all.ru/3.4/library/html.parser.html#id2), когда не сможет разобрать разметку. Использование `strict=True` не рекомендуется, а аргумент *strict* является устаревшим.2223Экземпляр [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) получает HTML-данные и вызывает методы-обработчики при обнаружении открывающих тегов, закрывающих тегов, текста, комментариев и других элементов разметки. Чтобы реализовать желаемое поведение, следует создать подкласс [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) и переопределить его методы.2425Этот парсер не проверяет, соответствуют ли закрывающие теги открывающим, и не вызывает обработчик закрывающего тега для элементов, которые неявно закрываются при закрытии внешнего элемента.2627Изменено в версии 3.2: добавлен аргумент *strict*.2829Устарело с версии 3.3, будет удалено в версии 3.5: Аргумент *strict* и строгий режим устарели. Теперь парсер также способен принимать и разбирать некорректную разметку.3031Изменено в версии 3.4: Добавлен аргумент *convert\_charrefs*.3233Также определено исключение:3435#### `exception html.parser.HTMLParseError`3637Исключение, возбуждаемое классом [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser), когда он обнаруживает ошибку при разборе и *strict* равен `True`. Это исключение предоставляет три атрибута: `msg` – краткое сообщение, объясняющее ошибку; `lineno` – номер строки, в которой обнаружен некорректный элемент; `offset` – количество символов от начала строки, где начинается этот элемент.3839Устарело с версии 3.3, будет удалено в версии 3.5: Это исключение было объявлено устаревшим, поскольку оно никогда не возбуждается парсером (при использовании режима нестрогого разбора по умолчанию).4041## 20.2.1. Пример приложения парсера HTML4243В качестве простого примера ниже приведён парсер HTML, использующий класс [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) для вывода открывающих тегов, закрывающих тегов и данных по мере их обнаружения:4445```python46from html.parser import HTMLParser4748class MyHTMLParser(HTMLParser):49    def handle_starttag(self, tag, attrs):50        print("Encountered a start tag:", tag)51    def handle_endtag(self, tag):52        print("Encountered an end tag :", tag)53    def handle_data(self, data):54        print("Encountered some data  :", data)5556parser = MyHTMLParser()57parser.feed('<html><head><title>Test</title></head>'58            '<body><h1>Parse me!</h1></body></html>')59```6061Результат будет таким:6263```python64Encountered a start tag: html65Encountered a start tag: head66Encountered a start tag: title67Encountered some data  : Test68Encountered an end tag : title69Encountered an end tag : head70Encountered a start tag: body71Encountered a start tag: h172Encountered some data  : Parse me!73Encountered an end tag : h174Encountered an end tag : body75Encountered an end tag : html76```7778## 20.2.2. Методы [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser)7980Экземпляры [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) имеют следующие методы:8182#### `HTMLParser.feed(data)`8384Передаёт парсеру текст. Он обрабатывается, пока состоит из завершённых элементов; неполные данные буферизуются до тех пор, пока не будут переданы новые данные или не будет вызван метод [`close()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.close). *data* должен иметь тип [`str`](https://python-all.ru/3.4/library/stdtypes.html#str).8586#### `HTMLParser.close()`8788Принудительно обрабатывает все буферизованные данные так, как если бы за ними следовал маркер конца файла. Этот метод может быть переопределён в производном классе для добавления обработки в конце входных данных, но переопределённая версия всегда должна вызывать метод базового класса [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) – [`close()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.close).8990#### `HTMLParser.reset()`9192Сбрасывает экземпляр. Теряет все необработанные данные. Вызывается неявно при создании экземпляра.9394#### `HTMLParser.getpos()`9596Возвращает номер текущей строки и смещение.9798#### `HTMLParser.get_starttag_text()`99100Возвращает текст самого последнего открытого начального тега. Обычно это не требуется для структурированной обработки, но может пригодиться при работе с HTML «как есть» или при повторной генерации входных данных с минимальными изменениями (пробелы между атрибутами можно сохранить и т.д.).101102Следующие методы вызываются при обнаружении данных или элементов разметки, и их предполагается переопределять в подклассе. Реализации базового класса ничего не делают (за исключением [`handle_startendtag()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.handle_startendtag)):103104#### `HTMLParser.handle_starttag(tag, attrs)`105106Этот метод вызывается для обработки открывающего тега (например, `<div id="main">`).107108Аргумент *tag* – это имя тега, приведённое к нижнему регистру. Аргумент *attrs* – это список пар `(name, value)`, содержащих атрибуты, найденные внутри `<>` скобок тега. *name* будет преобразован в нижний регистр, кавычки в *value* удаляются, а символьные и сущностные ссылки заменяются.109110Например, для тега `<A HREF="http://www.cwi.nl/">` этот метод был бы вызван как `handle_starttag('a', [('href', 'http://www.cwi.nl/')])`.111112Все ссылки на сущности из [`html.entities`](https://python-all.ru/3.4/library/html.entities.html#module-html.entities) заменяются в значениях атрибутов.113114#### `HTMLParser.handle_endtag(tag)`115116Этот метод вызывается для обработки закрывающего тега элемента (например, `</div>`).117118Аргумент *tag* – это имя тега, приведённое к нижнему регистру.119120#### `HTMLParser.handle_startendtag(tag, attrs)`121122Аналогичен [`handle_starttag()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.handle_starttag), но вызывается, когда парсер встречает пустой тег в стиле XHTML (`<img ... />`). Этот метод может быть переопределён подклассами, которым требуется эта лексическая информация; реализация по умолчанию просто вызывает [`handle_starttag()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.handle_starttag) и [`handle_endtag()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.handle_endtag).123124#### `HTMLParser.handle_data(data)`125126Этот метод вызывается для обработки произвольных данных (например, текстовых узлов и содержимого `<script>...</script>` и `<style>...</style>`).127128#### `HTMLParser.handle_entityref(name)`129130Этот метод вызывается для обработки именованной символьной ссылки вида `&name;` (например, `&gt;`), где *name* – это ссылка на общий объект (например, `'gt'`). Этот метод никогда не вызывается, если *convert\_charrefs* имеет значение `True`.131132#### `HTMLParser.handle_charref(name)`133134Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида `&#NNN;` и `&#xNNN;`. Например, десятичный эквивалент для `&gt;` – это `&#62;`, а шестнадцатеричный – `&#x3E;`; в этом случае метод получит `'62'` или `'x3E'`. Этот метод никогда не вызывается, если *convert\_charrefs* имеет значение `True`.135136#### `HTMLParser.handle_comment(data)`137138Этот метод вызывается, когда встречается комментарий (например, `<!--comment-->`).139140Например, комментарий `<!-- comment -->` приведёт к вызову этого метода с аргументом `' comment '`.141142Содержимое условных комментариев Internet Explorer (condcoms) также будет передано этому методу, поэтому для `<!--[if IE 9]>IE9-specific content<![endif]-->` этот метод получит `'[if IE 9]>IE9-specific content<![endif]'`.143144#### `HTMLParser.handle_decl(decl)`145146Этот метод вызывается для обработки объявления типа документа HTML (например, `<!DOCTYPE html>`).147148Параметр *decl* будет содержать всё содержимое объявления внутри разметки `<!...>` (например, `'DOCTYPE html'`).149150#### `HTMLParser.handle_pi(data)`151152Метод, вызываемый при обнаружении инструкции обработки. Параметр *data* будет содержать всю инструкцию обработки. Например, для инструкции обработки `<?proc color='red'>` этот метод будет вызван как `handle_pi("proc color='red'")`. Предназначен для переопределения в производном классе; реализация базового класса ничего не делает.153154> **Примечание**155>156> Класс [`HTMLParser`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser) использует синтаксические правила SGML для обработки инструкций. Инструкция обработки XHTML, использующая завершающий `'?'`, приведёт к включению `'?'` в *data*.157158#### `HTMLParser.unknown_decl(data)`159160Этот метод вызывается, когда парсер считывает нераспознанное объявление.161162Параметр *data* будет содержать всё содержимое объявления внутри разметки `<![...]>`. Иногда его полезно переопределять в производном классе. Реализация базового класса вызывает исключение [`HTMLParseError`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParseError), когда *strict* имеет значение `True`.163164## 20.2.3. Примеры165166Следующий класс реализует парсер, который будет использоваться для иллюстрации дополнительных примеров:167168```python169from html.parser import HTMLParser170from html.entities import name2codepoint171172class MyHTMLParser(HTMLParser):173    def handle_starttag(self, tag, attrs):174        print("Start tag:", tag)175        for attr in attrs:176            print("     attr:", attr)177    def handle_endtag(self, tag):178        print("End tag  :", tag)179    def handle_data(self, data):180        print("Data     :", data)181    def handle_comment(self, data):182        print("Comment  :", data)183    def handle_entityref(self, name):184        c = chr(name2codepoint[name])185        print("Named ent:", c)186    def handle_charref(self, name):187        if name.startswith('x'):188            c = chr(int(name[1:], 16))189        else:190            c = chr(int(name))191        print("Num ent  :", c)192    def handle_decl(self, data):193        print("Decl     :", data)194195parser = MyHTMLParser()196```197198Разбор объявления типа документа:199200```python201>>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '202...             '"http://www.w3.org/TR/html4/strict.dtd">')203Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"204```205206Разбор элемента с несколькими атрибутами и заголовком:207208```python209>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')210Start tag: img211     attr: ('src', 'python-logo.png')212     attr: ('alt', 'The Python logo')213>>>214>>> parser.feed('<h1>Python</h1>')215Start tag: h1216Data     : Python217End tag  : h1218```219220Содержимое элементов `script` и `style` возвращается как есть, без дальнейшего разбора:221222```python223>>> parser.feed('<style type="text/css">#python { color: green }</style>')224Start tag: style225     attr: ('type', 'text/css')226Data     : #python { color: green }227End tag  : style228>>>229>>> parser.feed('<script type="text/javascript">'230...             'alert("<strong>hello!</strong>");</script>')231Start tag: script232     attr: ('type', 'text/javascript')233Data     : alert("<strong>hello!</strong>");234End tag  : script235```236237Разбор комментариев:238239```python240>>> parser.feed('<!-- a comment -->'241...             '<!--[if IE 9]>IE-specific content<![endif]-->')242Comment  :  a comment243Comment  : [if IE 9]>IE-specific content<![endif]244```245246Разбор именованных и числовых символьных ссылок и преобразование их в соответствующий символ (примечание: эти три ссылки эквивалентны `'>'`):247248```python249>>> parser.feed('&gt;&#62;&#x3E;')250Named ent: >251Num ent  : >252Num ent  : >253```254255Передача неполных фрагментов в [`feed()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.feed) работает, но [`handle_data()`](https://python-all.ru/3.4/library/html.parser.html#html.parser.HTMLParser.handle_data) может быть вызван более одного раза (если только *convert\_charrefs* не установлен в `True`):256257```python258>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:259...     parser.feed(chunk)260...261Start tag: span262Data     : buff263Data     : ered264Data     : text265End tag  : span266```267268Разбор некорректного HTML (например, атрибуты без кавычек) также работает:269270```python271>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')272Start tag: p273Start tag: a274     attr: ('class', 'link')275     attr: ('href', '#main')276Data     : tag soup277End tag  : p278End tag  : a279```280281Сноски282283| [\[1\]](https://python-all.ru/3.4/library/html.parser.html#id1) | По причинам обратной совместимости режим *strict* не вызывает исключений для всего несоответствующего HTML. То есть некоторый некорректный HTML допускается даже в режиме *strict*. |284| --- | --- |285