html.parser
— Простой парсер HTML и XHTML
Данный модуль определяет класс HTMLParser
, который служит основой для
анализа текстовых файлов, отформатированных в HTML (язык гипертекстовой
разметки) и 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("Столкнулся с начальным тегом: ", tag)
def handle_endtag(self, tag):
print("Столкнулся с конечным тегом :", tag)
def handle_data(self, data):
print("Столкнулся с некоторыми данными :", data)
parser = MyHTMLParser()
parser.feed('<html><head><title>Test</title></head>'
'<body><h1>Parse me!</h1></body></html>')
Выход тогда будет:
Столкнулся с начальным тегом: html
Столкнулся с начальным тегом: head
Столкнулся с начальным тегом: title
Столкнулся с некоторыми данными : Test
Столкнулся с конечным тегом : title
Столкнулся с конечным тегом : head
Столкнулся с начальным тегом: body
Столкнулся с начальным тегом: h1
Столкнулся с некоторыми данными : Parse me!
Столкнулся с конечным тегом : h1
Столкнулся с конечным тегом : body
Столкнулся с конечным тегом : 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 удалены, а ссылки на символы и сущности заменены.Например, для тега
<A HREF="https://digitology.tech/">
данный метод будет называтьсяhandle_starttag('a', [('href', 'https://digitology.tech/')])
.Все ссылки на объекты из
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;
(например,>
), где name — это общая ссылка на объект (например,'gt'
). Данный метод никогда не вызывается, если convert_charrefs равенTrue
.
-
HTMLParser.
handle_charref
(name) Данный метод вызывается для обработки десятичных и шестнадцатеричных числовых ссылок на символы в форме
&#NNN;
и&#xNNN;
. Например, десятичный эквивалент для>
—>
, а шестнадцатеричный —>
; в этом случае метод получит'62'
или'x3E'
. Данный метод никогда не вызывается, если convert_charrefs равенTrue
.
-
HTMLParser.
handle_comment
(data) Данный метод вызывается при обнаружении комментария (например,
<!--comment-->
).Например, комментарий
<!-- comment -->
вызовет данный метод с аргументом' comment '
.Содержимое условных комментариев (condcom’ы) Internet Explorer также будет отправлено в данный метод, поэтому для
<!--[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("Начальный тег:", tag)
for attr in attrs:
print(" attr:", attr)
def handle_endtag(self, tag):
print("Конечный тег :", tag)
def handle_data(self, data):
print("Данные :", data)
def handle_comment(self, data):
print("Комментарий :", data)
def handle_entityref(self, name):
c = chr(name2codepoint[name])
print("Имя элемента :", c)
def handle_charref(self, name):
if name.startswith('x'):
c = chr(int(name[1:], 16))
else:
c = chr(int(name))
print("Номер элемента :", 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">')
Начальный тег: img
attr: ('src', 'python-logo.png')
attr: ('alt', 'The Python logo')
>>>
>>> parser.feed('<h1>Python</h1>')
Начальный тег: h1
Данные : Python
Конечный тег : h1
Содержимое элементов script
и style
возвращается как есть, без
дальнейшего анализа:
>>> parser.feed('<style type="text/css">#python { color: green }</style>')
Начальный тег: style
attr: ('type', 'text/css')
Данные : #python { color: green }
Конечный тег : style
>>> parser.feed('<script type="text/javascript">'
... 'alert("<strong>hello!</strong>");</script>')
Начальный тег: script
attr: ('type', 'text/javascript')
Данные : alert("<strong>hello!</strong>");
Конечный тег : script
Разбор комментариев:
>>> parser.feed('<!-- a comment -->'
... '<!--[if IE 9]>IE-specific content<![endif]-->')
Комментарий : a comment
Комментарий : [if IE 9]>IE-specific content<![endif]
Разбор ссылок на именованные и числовые символы и преобразование их в
правильный символ (примечание: все данные 3 ссылки эквивалентны '>'
):
>>> parser.feed('>>>')
Имя элемента : >
Номер элемента : >
Номер элемента : >
Передача неполных фрагментов в feed()
работает, но
handle_data()
может вызываться более одного раза (если для
convert_charrefs не установлено значение True
):
>>> for chunk in ['<sp', 'an>buff', 'ered ', 'text</s', 'pan>']:
... parser.feed(chunk)
...
Начальный тег: span
Данные : buff
Данные : ered
Данные : text
Конечный тег : span
Парсинг недопустимого HTML (например, атрибутов без кавычек) также работает:
>>> parser.feed('<p><a class=link href=#main>tag soup</p ></a>')
Начальный тег: p
Начальный тег: a
attr: ('class', 'link')
attr: ('href', '#main')
Данные : tag soup
Конечный тег : p
Конечный тег : a