Spec-Zone.ru › Python 3.14

html.parser — простой анализатор HTML и XHTML

Исходный код: Lib/html/parser.py

Этот модуль определяет класс HTMLParser, который служит основой для анализа текстовых файлов в формате HTML (HyperText Mark-up Language) и XHTML.

class html.parser.HTMLParser(*, convert_charrefs=True, scripting=False)

Создаёт экземпляр анализатора, способный анализировать некорректную разметку.

Если convert_charrefs имеет значение true (по умолчанию), все символьные ссылки (за исключением ссылок в элементах, таких как script и style) автоматически преобразуются в соответствующие символы Unicode.

Если scripting имеет значение false (по умолчанию), содержимое элемента noscript анализируется обычным образом; если true, оно возвращается без анализа.

Экземпляру HTMLParser передаются данные HTML, и он вызывает методы-обработчики при обнаружении открывающих и закрывающих тегов, текста, комментариев и других элементов разметки. Пользователь должен создать подкласс HTMLParser и переопределить его методы, чтобы реализовать нужное поведение.

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

Изменено в версии 3.4: Добавлен именованный аргумент convert_charrefs.

Изменено в версии 3.5: Теперь значение по умолчанию аргумента convert_charrefs — True.

Изменено в версии 3.14.1: Добавлен параметр scripting.

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

Например, для тега <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 и style).

HTMLParser.handle_entityref(name)

Этот метод вызывается для обработки именованной символьной ссылки вида &name; (например, &gt;), где name — это ссылка на общую сущность (например, 'gt'). Этот метод вызывается только в том случае, если convert_charrefs имеет значение false.

HTMLParser.handle_charref(name)

Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида &#NNN; и &#xNNN;. Например, десятичный эквивалент &gt; — &#62;, а шестнадцатеричный — &#x3E;; в этом случае метод получит '62' или 'x3E'. Этот метод вызывается только в том случае, если convert_charrefs имеет значение false.

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)

Этот метод вызывается для обработки объявления doctype в 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()

Анализ объявления doctype:

>>> 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! &#9786;</strong>");</script>')
Start tag: script
     attr: ('type', 'text/javascript')
Data     : alert("<strong>hello! &#9786;</strong>");
End tag  : script

Имена атрибутов преобразуются в нижний регистр, кавычки в значениях атрибутов удаляются, а None возвращается как значение value для пустых атрибутов (например, checked):

>>> parser.feed("<input TYPE='checkbox' checked required='' disabled=disabled>")
Start tag: input
     attr: ('type', 'checkbox')
     attr: ('checked', None)
     attr: ('required', '')
     attr: ('disabled', 'disabled')

Анализ комментариев:

>>> parser.feed('<!--a comment-->'
...             '<!--[if IE 9]>IE-specific content<![endif]-->')
Comment  : a comment
Comment  : [if IE 9]>IE-specific content<![endif]

Анализ именованных и числовых символьных ссылок и преобразование их в соответствующий символ (примечание: все эти 3 ссылки эквивалентны '>'):

>>> parser = MyHTMLParser()
>>> parser.feed('&gt;&#62;&#x3E;')
Data     : >>>

>>> parser = MyHTMLParser(convert_charrefs=False)
>>> parser.feed('&gt;&#62;&#x3E;')
Named ent: >
Num ent  : >
Num ent  : >

Передача неполных фрагментов в feed() работает, но handle_data() может вызываться несколько раз, если convert_charrefs имеет значение false:

>>> 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 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.14/library/html.parser.html

Spec-Zone.ru

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