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(). данные должны быть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://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;(например,>), где name - общая ссылка на сущность (например,'gt'). Этот метод никогда не вызывается, если convert_charrefs имеет значениеTrue.
-
HTMLParser.handle_charref(name)¶ Этот метод вызывается для обработки десятичных и шестнадцатеричных числовых символьных ссылок вида
&#NNN;и&#xNNN;. Например, десятичным эквивалентом для>является>, а шестнадцатеричным ->; в этом случае метод получит'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 (например,
<!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
Разбор комментариев:
>>> 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('>>>')
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