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

htmlparser.md

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

1> **Источник:** https://python-all.ru/2.7/library/htmlparser.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 19.1. [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#module-HTMLParser) – Простой парсер HTML и XHTML89> **Примечание**10>11> Модуль [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#module-HTMLParser) переименован в `html.parser` в Python 3. Инструмент [2to3](https://python-all.ru/2.7/glossary.html#term-2to3) автоматически адаптирует импорты при преобразовании исходных кодов в Python 3.1213Новое в версии 2.2.1415**Исходный код:** [Lib/HTMLParser.py](https://python-all.ru/src/2.7/Lib/HTMLParser.py)1617---1819Этот модуль определяет класс [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser), который служит основой для разбора текстовых файлов в формате HTML (язык гипертекстовой разметки) и XHTML. В отличие от парсера в [`htmllib`](https://python-all.ru/2.7/library/htmllib.html#module-htmllib), этот парсер не основан на SGML-парсере из [`sgmllib`](https://python-all.ru/2.7/library/sgmllib.html#module-sgmllib).2021#### `class HTMLParser.HTMLParser`2223Экземпляр [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) получает HTML-данные и вызывает методы-обработчики при обнаружении открывающих тегов, закрывающих тегов, текста, комментариев и других элементов разметки. Пользователь должен создать подкласс [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) и переопределить его методы для реализации нужного поведения.2425Класс [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) создаётся без аргументов.2627В отличие от парсера в [`htmllib`](https://python-all.ru/2.7/library/htmllib.html#module-htmllib), этот парсер не проверяет, что закрывающие теги соответствуют открывающим, и не вызывает обработчик закрывающего тега для элементов, которые закрываются неявно при закрытии внешнего элемента.2829Также определено исключение:3031#### `exception HTMLParser.HTMLParseError`3233[`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) способен обрабатывать некорректную разметку, но в некоторых случаях может вызвать это исключение при обнаружении ошибки во время разбора. Это исключение предоставляет три атрибута: `msg` – краткое сообщение с описанием ошибки, `lineno` – номер строки, в которой была обнаружена некорректная конструкция, и `offset` – количество символов от начала строки до начала этой конструкции.3435## 19.1.1. Пример приложения парсера HTML3637В качестве простого примера ниже приведён HTML-парсер, использующий класс [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) для вывода начальных тегов, конечных тегов и данных по мере их появления:3839```python40from HTMLParser import HTMLParser4142# создать подкласс и переопределить методы-обработчики43class MyHTMLParser(HTMLParser):44    def handle_starttag(self, tag, attrs):45        print "Encountered a start tag:", tag4647    def handle_endtag(self, tag):48        print "Encountered an end tag :", tag4950    def handle_data(self, data):51        print "Encountered some data  :", data5253# создать экземпляр парсера и передать ему некоторый HTML54parser = MyHTMLParser()55parser.feed('<html><head><title>Test</title></head>'56            '<body><h1>Parse me!</h1></body></html>')57```5859Результат будет таким:6061```text62Encountered a start tag: html63Encountered a start tag: head64Encountered a start tag: title65Encountered some data  : Test66Encountered an end tag : title67Encountered an end tag : head68Encountered a start tag: body69Encountered a start tag: h170Encountered some data  : Parse me!71Encountered an end tag : h172Encountered an end tag : body73Encountered an end tag : html74```7576## 19.1.2. [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) Методы7778Экземпляры [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) имеют следующие методы:7980#### `HTMLParser.feed(data)`8182Передаёт парсеру текст. Он обрабатывается, насколько состоит из полных элементов; неполные данные буферизуются до тех пор, пока не будет передан ещё текст или не будет вызван [`close()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.close). *данные* может быть как [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode), так и [`str`](https://python-all.ru/2.7/library/functions.html#str), но рекомендуется передавать [`unicode`](https://python-all.ru/2.7/library/functions.html#unicode).8384#### `HTMLParser.close()`8586Принудительно обрабатывает все буферизованные данные так, как если бы за ними следовал маркер конца файла. Этот метод может быть переопределён в производном классе для дополнительной обработки в конце входных данных, но переопределённая версия всегда должна вызывать метод [`close()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.close) базового класса [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser).8788#### `HTMLParser.reset()`8990Сбрасывает экземпляр. Теряет все необработанные данные. Вызывается неявно при создании экземпляра.9192#### `HTMLParser.getpos()`9394Возвращает номер текущей строки и смещение.9596#### `HTMLParser.get_starttag_text()`9798Возвращает текст самого последнего открытого начального тега. Обычно это не требуется для структурированной обработки, но может пригодиться при работе с HTML «как есть» или при повторной генерации входных данных с минимальными изменениями (пробелы между атрибутами можно сохранить и т.д.).99100Следующие методы вызываются при обнаружении данных или элементов разметки, и их предполагается переопределять в подклассе. Реализации базового класса ничего не делают (кроме [`handle_startendtag()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.handle_startendtag)):101102#### `HTMLParser.handle_starttag(tag, attrs)`103104Этот метод вызывается для обработки открывающего тега (например, `<div id="main">`).105106Аргумент *tag* – это имя тега, приведённое к нижнему регистру. Аргумент *attrs* – это список пар `(name, value)`, содержащих атрибуты, найденные внутри угловых скобок тега `<>`. Имя *name* будет приведено к нижнему регистру, кавычки в значении *value* удалены, а символьные и сущностные ссылки заменены.107108Например, для тега `<A HREF="https://www.cwi.nl/">` этот метод будет вызван как `handle_starttag('a', [('href', 'https://www.cwi.nl/')])`.109110Изменено в версии 2.6: Все ссылки на сущности из [`htmlentitydefs`](https://python-all.ru/2.7/library/htmllib.html#module-htmlentitydefs) теперь заменяются в значениях атрибутов.111112#### `HTMLParser.handle_endtag(tag)`113114Этот метод вызывается для обработки закрывающего тега элемента (например, `</div>`).115116Аргумент *tag* – это имя тега, приведённое к нижнему регистру.117118#### `HTMLParser.handle_startendtag(tag, attrs)`119120Аналогично [`handle_starttag()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.handle_starttag), но вызывается, когда парсер встречает пустой тег в стиле XHTML (`<img ... />`). Этот метод может быть переопределён подклассами, которым требуется эта конкретная лексическая информация; реализация по умолчанию просто вызывает [`handle_starttag()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.handle_starttag) и [`handle_endtag()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.handle_endtag).121122#### `HTMLParser.handle_data(data)`123124Этот метод вызывается для обработки произвольных данных (например, текстовых узлов и содержимого `<script>...</script>` и `<style>...</style>`).125126#### `HTMLParser.handle_entityref(name)`127128Этот метод вызывается для обработки именованной символьной ссылки вида `&name;` (например `&gt;`), где *имя* – ссылка на общую сущность (например `'gt'`).129130#### `HTMLParser.handle_charref(name)`131132Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида `&#NNN;` и `&#xNNN;`. Например, десятичный эквивалент для `&gt;``&#62;`, а шестнадцатеричный – `&#x3E;`; в этом случае метод получит `'62'` или `'x3E'`.133134#### `HTMLParser.handle_comment(data)`135136Этот метод вызывается, когда встречается комментарий (например, `<!--comment-->`).137138Например, комментарий `<!-- comment -->` приведёт к вызову этого метода с аргументом `' comment '`.139140Содержимое условных комментариев Internet Explorer (condcoms) также будет передано этому методу, поэтому для `<!--[if IE 9]>IE9-specific content<![endif]-->` этот метод получит `'[if IE 9]>IE9-specific content<![endif]'`.141142#### `HTMLParser.handle_decl(decl)`143144Этот метод вызывается для обработки объявления типа документа HTML (например, `<!DOCTYPE html>`).145146Параметр *decl* будет содержать всё содержимое объявления внутри разметки `<!...>` (например, `'DOCTYPE html'`).147148#### `HTMLParser.handle_pi(data)`149150Этот метод вызывается при обнаружении инструкции обработки. Параметр *данные* будет содержать всю инструкцию обработки. Например, для инструкции обработки `<?proc color='red'>` этот метод будет вызван как `handle_pi("proc color='red'")`.151152> **Примечание**153>154> Класс [`HTMLParser`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser) использует синтаксические правила SGML для инструкций обработки. Инструкция обработки XHTML с завершающим `'?'` приведёт к тому, что `'?'` будет включено в *data*.155156#### `HTMLParser.unknown_decl(data)`157158Этот метод вызывается, когда парсер считывает нераспознанное объявление.159160Параметр *данные* будет содержать всё содержимое объявления внутри разметки `<![...]>`. Иногда его полезно переопределять в производном классе.161162## 19.1.3. Примеры163164Следующий класс реализует парсер, который будет использоваться для иллюстрации дополнительных примеров:165166```python167from HTMLParser import HTMLParser168from htmlentitydefs import name2codepoint169170class MyHTMLParser(HTMLParser):171    def handle_starttag(self, tag, attrs):172        print "Start tag:", tag173        for attr in attrs:174            print "     attr:", attr175176    def handle_endtag(self, tag):177        print "End tag  :", tag178179    def handle_data(self, data):180        print "Data     :", data181182    def handle_comment(self, data):183        print "Comment  :", data184185    def handle_entityref(self, name):186        c = unichr(name2codepoint[name])187        print "Named ent:", c188189    def handle_charref(self, name):190        if name.startswith('x'):191            c = unichr(int(name[1:], 16))192        else:193            c = unichr(int(name))194        print "Num ent  :", c195196    def handle_decl(self, data):197        print "Decl     :", data198199parser = MyHTMLParser()200```201202Разбор объявления типа документа:203204```python205>>> parser.feed('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '206...             '"http://www.w3.org/TR/html4/strict.dtd">')207Decl     : DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"208```209210Разбор элемента с несколькими атрибутами и заголовком:211212```python213>>> parser.feed('<img src="python-logo.png" alt="The Python logo">')214Start tag: img215     attr: ('src', 'python-logo.png')216     attr: ('alt', 'The Python logo')217>>>218>>> parser.feed('<h1>Python</h1>')219Start tag: h1220Data     : Python221End tag  : h1222```223224Содержимое элементов `script` и `style` возвращается как есть, без дальнейшего разбора:225226```python227>>> parser.feed('<style type="text/css">#python { color: green }</style>')228Start tag: style229     attr: ('type', 'text/css')230Data     : #python { color: green }231End tag  : style232233>>> parser.feed('<script type="text/javascript">'234...             'alert("<strong>hello!</strong>");</script>')235Start tag: script236     attr: ('type', 'text/javascript')237Data     : alert("<strong>hello!</strong>");238End tag  : script239```240241Разбор комментариев:242243```python244>>> parser.feed('<!-- a comment -->'245...             '<!--[if IE 9]>IE-specific content<![endif]-->')246Comment  :  a comment247Comment  : [if IE 9]>IE-specific content<![endif]248```249250Разбор именованных и числовых символьных ссылок и преобразование их в соответствующий символ (примечание: эти три ссылки эквивалентны `'>'`):251252```python253>>> parser.feed('&gt;&#62;&#x3E;')254Named ent: >255Num ent  : >256Num ent  : >257```258259Передача неполных фрагментов в [`feed()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.feed) работает, но [`handle_data()`](https://python-all.ru/2.7/library/htmlparser.html#HTMLParser.HTMLParser.handle_data) может быть вызван более одного раза:260261```python262>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:263...     parser.feed(chunk)264...265Start tag: span266Data     : buff267Data     : ered268Data     : text269End tag  : span270```271272Разбор некорректного HTML (например, атрибуты без кавычек) также работает:273274```python275>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')276Start tag: p277Start tag: a278     attr: ('class', 'link')279     attr: ('href', '#main')280Data     : tag soup281End tag  : p282End tag  : a283```284