19.1. HTMLParser —シンプルなHTMLおよびXHTMLパーサー—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/2.7/library/htmlparser
移動先:案内検索

19.1。 HTMLParser —単純なHTMLおよびXHTMLパーサー

ノート

HTMLParser モジュールは、Python3でhtml.parserに名前が変更されました。 2to3 ツールは、ソースをPython 3に変換するときに、インポートを自動的に適応させます。


バージョン2.2の新機能。


ソースコード: :source: `Lib / HTMLParser.py`



このモジュールは、HTML(ハイパーテキストマークアップ言語)およびXHTMLでフォーマットされたテキストファイルを解析するための基礎として機能するクラス HTMLParser を定義します。 htmllib のパーサーとは異なり、このパーサーは sgmllib のSGMLパーサーに基づいていません。

class HTMLParser.HTMLParser

HTMLParser インスタンスにはHTMLデータが供給され、開始タグ、終了タグ、テキスト、コメント、およびその他のマークアップ要素が検出されると、ハンドラーメソッドが呼び出されます。 ユーザーは、 HTMLParser をサブクラス化し、そのメソッドをオーバーライドして、目的の動作を実装する必要があります。

HTMLParser クラスは、引数なしでインスタンス化されます。

htmllib のパーサーとは異なり、このパーサーは、終了タグが開始タグと一致するかどうかをチェックしたり、外部要素を閉じることによって暗黙的に閉じられた要素の終了タグハンドラーを呼び出したりしません。

例外も定義されています:

exception HTMLParser.HTMLParseError
HTMLParser は壊れたマークアップを処理できますが、解析中にエラーが発生した場合にこの例外が発生する場合があります。 この例外は3つの属性を提供します。msgはエラーを説明する短いメッセージ、linenoは壊れた構成が検出された行の番号、offsetは番号です。構成が始まる行への文字の数。

19.1.1。 HTMLパーサーアプリケーションの例

基本的な例として、以下は HTMLParser クラスを使用して、開始タグ、終了タグ、およびデータが検出されたときにそれらを出力する単純なHTMLパーサーです。

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

19.1.2。 HTMLParser メソッド

HTMLParser インスタンスには次のメソッドがあります。

HTMLParser.feed(data)
パーサーにテキストをフィードします。 完全な要素で構成されている限り、処理されます。 不完全なデータは、さらにデータが供給されるか、 close()が呼び出されるまでバッファリングされます。 dataunicode または 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)ペアのリストです。 name は小文字に変換され、 value の引用符は削除され、文字とエンティティの参照は置き換えられました。

たとえば、タグ<A HREF="https://www.cwi.nl/%22>の場合、このメソッドは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;の形式の10進数および16進数の数字参照を処理するために呼び出されます。 たとえば、&gt;に相当する10進数は&#62;ですが、16進数は&#x3E;です。 この場合、メソッドは'62'または'x3E'を受け取ります。
HTMLParser.handle_comment(data)

このメソッドは、コメントが検出されたときに呼び出されます(例: <!--comment-->)。

たとえば、コメント<!-- comment -->を指定すると、このメソッドは引数' comment 'で呼び出されます。

Internet Explorerの条件付きコメント(condcom)のコンテンツもこのメソッドに送信されるため、<!--[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処理命令により、'?'データに含まれます。

HTMLParser.unknown_decl(data)

このメソッドは、認識されない宣言がパーサーによって読み取られたときに呼び出されます。

data パラメーターは、<![...]>マークアップ内の宣言の内容全体になります。 派生クラスによってオーバーライドされると便利な場合があります。


19.1.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()

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('&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