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

html.parser.md

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

1> **Источник:** https://python-all.ru/3.8/library/html.parser.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`html.parser`](https://python-all.ru/3.8/library/html.parser.html#module-html.parser) – Простой парсер HTML и XHTML89**Исходный код:** [Lib/html/parser.py](https://python-all.ru/src/3.8/Lib/html/parser.py)1011---1213Этот модуль определяет класс [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser), который служит основой для разбора текстовых файлов в форматах HTML (HyperText Mark-up Language) и XHTML.1415#### `class html.parser.HTMLParser(*, convert_charrefs=True)`1617Создаёт экземпляр парсера, способный разбирать некорректную разметку.1819Если *convert\_charrefs* равно `True` (по умолчанию), все символьные ссылки (кроме тех, что находятся в элементах `script`/`style`) автоматически преобразуются в соответствующие символы Unicode.2021Экземпляр [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) получает HTML-данные и вызывает методы-обработчики при обнаружении открывающих тегов, закрывающих тегов, текста, комментариев и других элементов разметки. Пользователь должен создать подкласс [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) и переопределить его методы для реализации нужного поведения.2223Этот парсер не проверяет, соответствуют ли закрывающие теги открывающим, и не вызывает обработчик закрывающего тега для элементов, которые неявно закрываются при закрытии внешнего элемента.2425Изменено в версии 3.4: Добавлен аргумент *convert\_charrefs*.2627Изменено в версии 3.5: Значением по умолчанию для аргумента *convert\_charrefs* теперь является `True`.2829## Пример приложения парсера HTML3031В качестве простого примера ниже показан парсер HTML, использующий класс [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) для вывода открывающих тегов, закрывающих тегов и данных по мере их обнаружения:3233```python34from html.parser import HTMLParser3536class MyHTMLParser(HTMLParser):37    def handle_starttag(self, tag, attrs):38        print("Encountered a start tag:", tag)3940    def handle_endtag(self, tag):41        print("Encountered an end tag :", tag)4243    def handle_data(self, data):44        print("Encountered some data  :", data)4546parser = MyHTMLParser()47parser.feed('<html><head><title>Test</title></head>'48            '<body><h1>Parse me!</h1></body></html>')49```5051Результат будет таким:5253```text54Encountered a start tag: html55Encountered a start tag: head56Encountered a start tag: title57Encountered some data  : Test58Encountered an end tag : title59Encountered an end tag : head60Encountered a start tag: body61Encountered a start tag: h162Encountered some data  : Parse me!63Encountered an end tag : h164Encountered an end tag : body65Encountered an end tag : html66```6768## [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) Методы6970Экземпляры [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) имеют следующие методы:7172#### `HTMLParser.feed(data)`7374Передаёт текст парсеру. Текст обрабатывается постольку, поскольку состоит из полных элементов; неполные данные буферизуются до тех пор, пока не будут переданы новые данные или не будет вызван [`close()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.close). Аргумент *data* должен быть [`str`](https://python-all.ru/3.8/library/stdtypes.html#str).7576#### `HTMLParser.close()`7778Принудительно обрабатывает все буферизованные данные так, как если бы за ними следовал маркер конца файла. Этот метод может быть переопределён в производном классе для дополнительной обработки в конце входных данных, но переопределённая версия всегда должна вызывать метод [`close()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.close) базового класса [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser).7980#### `HTMLParser.reset()`8182Сбрасывает экземпляр. Теряет все необработанные данные. Вызывается неявно при создании экземпляра.8384#### `HTMLParser.getpos()`8586Возвращает номер текущей строки и смещение.8788#### `HTMLParser.get_starttag_text()`8990Возвращает текст самого последнего открытого начального тега. Обычно это не требуется для структурированной обработки, но может пригодиться при работе с HTML «как есть» или при повторной генерации входных данных с минимальными изменениями (пробелы между атрибутами можно сохранить и т.д.).9192Следующие методы вызываются при обнаружении данных или элементов разметки, и их предполагается переопределять в подклассе. Реализации базового класса ничего не делают (кроме [`handle_startendtag()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.handle_startendtag)):9394#### `HTMLParser.handle_starttag(tag, attrs)`9596Этот метод вызывается для обработки открывающего тега (например, `<div id="main">`).9798Аргумент *tag* – это имя тега, приведённое к нижнему регистру. Аргумент *attrs* – это список пар `(name, value)`, содержащих атрибуты, найденные внутри угловых скобок тега `<>`. Имя *name* будет приведено к нижнему регистру, кавычки в значении *value* удалены, а символьные и сущностные ссылки заменены.99100Например, для тега `<A HREF="https://www.cwi.nl/">` этот метод будет вызван как `handle_starttag('a', [('href', 'https://www.cwi.nl/')])`.101102Все ссылки на сущности из [`html.entities`](https://python-all.ru/3.8/library/html.entities.html#module-html.entities) заменяются в значениях атрибутов.103104#### `HTMLParser.handle_endtag(tag)`105106Этот метод вызывается для обработки закрывающего тега элемента (например, `</div>`).107108Аргумент *tag* – это имя тега, приведённое к нижнему регистру.109110#### `HTMLParser.handle_startendtag(tag, attrs)`111112Аналогично [`handle_starttag()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.handle_starttag), но вызывается, когда парсер встречает пустой тег в стиле XHTML (`<img ... />`). Этот метод может быть переопределён подклассами, которым требуется эта конкретная лексическая информация; реализация по умолчанию просто вызывает [`handle_starttag()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.handle_starttag) и [`handle_endtag()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.handle_endtag).113114#### `HTMLParser.handle_data(data)`115116Этот метод вызывается для обработки произвольных данных (например, текстовых узлов и содержимого `<script>...</script>` и `<style>...</style>`).117118#### `HTMLParser.handle_entityref(name)`119120Этот метод вызывается для обработки именованной символьной ссылки вида `&name;` (например, `&gt;`), где *name* – это ссылка на общую сущность (например, `'gt'`). Этот метод никогда не вызывается, если *convert\_charrefs* равно `True`.121122#### `HTMLParser.handle_charref(name)`123124Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида `&#NNN;` и `&#xNNN;`. Например, десятичный эквивалент для `&gt;` – это `&#62;`, а шестнадцатеричный – `&#x3E;`; в этом случае метод получит `'62'` или `'x3E'`. Этот метод никогда не вызывается, если *convert\_charrefs* равно `True`.125126#### `HTMLParser.handle_comment(data)`127128Этот метод вызывается, когда встречается комментарий (например, `<!--comment-->`).129130Например, комментарий `<!-- comment -->` приведёт к вызову этого метода с аргументом `' comment '`.131132Содержимое условных комментариев Internet Explorer (condcoms) также будет передано этому методу, поэтому для `<!--[if IE 9]>IE9-specific content<![endif]-->` этот метод получит `'[if IE 9]>IE9-specific content<![endif]'`.133134#### `HTMLParser.handle_decl(decl)`135136Этот метод вызывается для обработки объявления типа документа HTML (например, `<!DOCTYPE html>`).137138Параметр *decl* будет содержать всё содержимое объявления внутри разметки `<!...>` (например, `'DOCTYPE html'`).139140#### `HTMLParser.handle_pi(data)`141142Метод, вызываемый при обнаружении инструкции обработки. Параметр *data* будет содержать всю инструкцию обработки. Например, для инструкции обработки `<?proc color='red'>` этот метод будет вызван как `handle_pi("proc color='red'")`. Он предназначен для переопределения в производном классе; реализация базового класса ничего не делает.143144> **Примечание**145>146> Класс [`HTMLParser`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser) использует синтаксические правила SGML для инструкций обработки. Инструкция обработки XHTML с завершающим `'?'` приведёт к тому, что `'?'` будет включено в *data*.147148#### `HTMLParser.unknown_decl(data)`149150Этот метод вызывается, когда парсер считывает нераспознанное объявление.151152Параметр *data* будет содержать всё содержимое объявления внутри разметки `<![...]>`. Иногда его полезно переопределять в производном классе. Реализация базового класса ничего не делает.153154## Примеры155156Следующий класс реализует парсер, который будет использоваться для иллюстрации дополнительных примеров:157158```python159from html.parser import HTMLParser160from html.entities import name2codepoint161162class MyHTMLParser(HTMLParser):163    def handle_starttag(self, tag, attrs):164        print("Start tag:", tag)165        for attr in attrs:166            print("     attr:", attr)167168    def handle_endtag(self, tag):169        print("End tag  :", tag)170171    def handle_data(self, data):172        print("Data     :", data)173174    def handle_comment(self, data):175        print("Comment  :", data)176177    def handle_entityref(self, name):178        c = chr(name2codepoint[name])179        print("Named ent:", c)180181    def handle_charref(self, name):182        if name.startswith('x'):183            c = chr(int(name[1:], 16))184        else:185            c = chr(int(name))186        print("Num ent  :", c)187188    def handle_decl(self, data):189        print("Decl     :", data)190191parser = MyHTMLParser()192```193194Разбор объявления типа документа:195196```python197>>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '198...             '"http://www.w3.org/TR/html4/strict.dtd">')199Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"200```201202Разбор элемента с несколькими атрибутами и заголовком:203204```python205>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')206Start tag: img207     attr: ('src', 'python-logo.png')208     attr: ('alt', 'The Python logo')209>>>210>>> parser.feed('<h1>Python</h1>')211Start tag: h1212Data     : Python213End tag  : h1214```215216Содержимое элементов `script` и `style` возвращается как есть, без дальнейшего разбора:217218```python219>>> parser.feed('<style type="text/css">#python { color: green }</style>')220Start tag: style221     attr: ('type', 'text/css')222Data     : #python { color: green }223End tag  : style224225>>> parser.feed('<script type="text/javascript">'226...             'alert("<strong>hello!</strong>");</script>')227Start tag: script228     attr: ('type', 'text/javascript')229Data     : alert("<strong>hello!</strong>");230End tag  : script231```232233Разбор комментариев:234235```python236>>> parser.feed('<!-- a comment -->'237...             '<!--[if IE 9]>IE-specific content<![endif]-->')238Comment  :  a comment239Comment  : [if IE 9]>IE-specific content<![endif]240```241242Разбор именованных и числовых символьных ссылок и преобразование их в соответствующий символ (примечание: эти три ссылки эквивалентны `'>'`):243244```python245>>> parser.feed('&gt;&#62;&#x3E;')246Named ent: >247Num ent  : >248Num ent  : >249```250251Передача неполных фрагментов в [`feed()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.feed) работает, но [`handle_data()`](https://python-all.ru/3.8/library/html.parser.html#html.parser.HTMLParser.handle_data) может быть вызван более одного раза (если только *convert\_charrefs* не установлен в `True`):252253```python254>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:255...     parser.feed(chunk)256...257Start tag: span258Data     : buff259Data     : ered260Data     : text261End tag  : span262```263264Разбор некорректного HTML (например, атрибуты без кавычек) также работает:265266```python267>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')268Start tag: p269Start tag: a270     attr: ('class', 'link')271     attr: ('href', '#main')272Data     : tag soup273End tag  : p274End tag  : a275```276