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() -
Принудительно обрабатывает все буферизованные данные, как если бы за ними следовал маркер конца файла. Этот метод можно переопределить в производном классе, чтобы определить дополнительную обработку в конце ввода, однако переопределённая версия должна всегда вызывать метод базового класса
HTMLParserclose().
-
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;(например,>), где name — это ссылка на общую сущность (например,'gt'). Этот метод вызывается только в том случае, если convert_charrefs имеет значение false.
-
HTMLParser.handle_charref(name) -
Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида
&#NNN;и&#xNNN;. Например, десятичный эквивалент>—>, а шестнадцатеричный —>; в этом случае метод получит'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! ☺</strong>");</script>')
Start tag: script
attr: ('type', 'text/javascript')
Data : alert("<strong>hello! ☺</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('>>>')
Data : >>>
>>> parser = MyHTMLParser(convert_charrefs=False)
>>> parser.feed('>>>')
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