Spec-Zone.ru › Python 2.7

HTMLParser — Простой парсер HTML и XHTML

Примечание

Модуль HTMLParser был переименован в html.parser в Python 3. Инструмент 2to3 автоматически адаптирует импорты при преобразовании исходного кода в Python 3.

Впервые в версии 2.2.

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

В этом модуле определен класс HTMLParser, который служит основой для разбора текстовых файлов, отформатированных в HTML (HyperText Mark-up Language) и XHTML. В отличие от парсера в htmllib, этот парсер не основан на SGML-парсере из sgmllib.

class HTMLParser.HTMLParser

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

Класс HTMLParser инициализируется без аргументов.

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

Также определено исключение:

exception HTMLParser.HTMLParseError

HTMLParser способен обрабатывать некорректную разметку, но в некоторых случаях может вызывать это исключение при обнаружении ошибки во время разбора. Это исключение предоставляет три атрибута: msg — краткое сообщение, объясняющее ошибку, lineno — номер строки, в которой была обнаружена некорректная конструкция, и offset — номер символа в строке, с которого начинается конструкция.

1. Пример применения парсера HTML

В качестве простого примера ниже представлен простой парсер HTML, который использует класс HTMLParser для вывода открывающихся тегов, закрывающихся тегов и данных по мере их обнаружения:

from HTMLParser import HTMLParser

# create a subclass and override the handler methods
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

# instantiate the parser and fed it some HTML
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

2. Методы HTMLParser

Экземпляры класса HTMLParser имеют следующие методы:

HTMLParser.feed(data)

Передать текст парсеру. Он обрабатывается по мере того, как он состоит из полных элементов; неполные данные буферизуются до тех пор, пока не будут переданы дополнительные данные или вызван метод close(). data может быть как unicode, так и str, но рекомендуется передавать unicode.

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

Например, для тега <A HREF="https://www.cwi.nl/">, этот метод будет вызван как handle_starttag('a', [('href', 'https://www.cwi.nl/')]).

Изменено в версии 2.6: Все ссылки на сущности из htmlentitydefs теперь заменяются в значениях атрибутов.

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').

HTMLParser.handle_charref(name)

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

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 будет содержать все содержимое объявления внутри <![...]> разметки. Иногда бывает полезно переопределить его в производном классе.

3. Примеры

Следующий класс реализует парсер, который будет использован для иллюстрации дополнительных примеров:

from HTMLParser import HTMLParser
from htmlentitydefs 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 = unichr(name2codepoint[name])
        print "Named ent:", c

    def handle_charref(self, name):
        if name.startswith('x'):
            c = unichr(int(name[1:], 16))
        else:
            c = unichr(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() может быть вызван более одного раза:

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

Spec-Zone.ru

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