Spec-Zone.ru › Python 3.8

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(). data должен быть 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) , содержащих атрибуты, найденные внутри <> скобок тега. Имя будет преобразовано в нижний регистр, а кавычки в значении 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 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()

Разбор типа документа:

>>> 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

© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/html.parser.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API