html.parser --- HTML と XHTML のシンプルなパーサー¶
ソースコード: Lib/html/parser.py
このモジュールでは HTMLParser クラスを定義します。このクラスは HTML (ハイパーテキスト記述言語、HyperText Mark-up Language) および XHTML で書式化されているテキストファイルを解釈するための基礎となります。
- class html.parser.HTMLParser(*, convert_charrefs=True, scripting=False)¶
不正なマークアップをパースできるパーサーインスタンスを作成します。
If convert_charrefs is true (the default), all character references (except the ones in elements like
scriptandstyle) are automatically converted to the corresponding Unicode characters.If scripting is false (the default), the content of the
noscriptelement is parsed normally; if it's true, it's returned as is without being parsed.HTMLParserインスタンスに HTML データを渡すと、開始タグ、終了タグ、テキスト、コメント、その他のマークアップ要素を見つけるたびにハンドラーメソッドを呼び出します。 利用者はHTMLParserのサブクラスを作り、メソッドをオーバーライドして必要な動作を実装します。このパーサーは終了タグが開始タグと一致しているか調べたり、外側のタグ要素が閉じるときに内側で明示的に閉じられていないタグ要素のタグ終了ハンドラーを呼び出したりはしません。
バージョン 3.4 で変更: キーワード引数 convert_charrefs を追加。
バージョン 3.5 で変更: convert_charrefs のデフォルト値は
Trueになりました。バージョン 3.13.10 で変更: Added the scripting parameter.
HTML パーサーアプリケーションの例¶
基本的な例として、以下は HTMLParser クラスを使い、開始タグ、終了タグ、データを見つけるたびに表示するシンプルな HTML パーサーです。
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()¶
全てのバッファーされているデータについて、その後にファイル終端マークが続いているとみなして強制的に処理を行います。このメソッドは入力データの終端で行う追加処理を定義するために、派生クラスで再定義することができます。しかし、再定義されたバージョンでは、常に
HTMLParser基底クラスのメソッドclose()を呼び出さなくてはなりません。
- HTMLParser.reset()¶
インスタンスをリセットします。未処理のデータはすべて失われます。インスタンス化の際に暗黙的に呼び出されます。
- HTMLParser.getpos()¶
現在の行番号およびオフセット値を返します。
- HTMLParser.get_starttag_text()¶
最後に読み込んだ開始タグのテキストを返します。 構造に基づく処理では通常は不要ですが、実際に使われている HTML を扱ったり、入力を最小限の変更で再生成したりする場合に役立つことがあります (属性間の空白などを保持できます)。
以下のメソッドはデータまたはマークアップ要素が見つかる度に呼び出されます。これらはサブクラスで上書きされることを想定されています。基底クラスの実装は (handle_startendtag() を除き) 何もしません:
- HTMLParser.handle_starttag(tag, attrs)¶
このメソッドは要素の開始タグを扱うために呼び出されます (例:
<div id="main">)。The tag argument is the name of the tag converted to lower case. The attrs argument is a list of
(name, value)pairs containing the attributes found inside the tag's<>brackets. The name will be translated to lower case, and quotes in the value have been removed, and character and entity references have been replaced. For empty attributes, value isNone.例えば、タグ
<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)¶
This method is called to process arbitrary data (e.g. text nodes and the content of elements like
scriptandstyle).
- HTMLParser.handle_entityref(name)¶
This method is called to process a named character reference of the form
&name;(e.g.>), where name is a general entity reference (e.g.'gt'). This method is only called if convert_charrefs is false.
- HTMLParser.handle_charref(name)¶
This method is called to process decimal and hexadecimal numeric character references of the form
&#NNN;and&#xNNN;. For example, the decimal equivalent for>is>, whereas the hexadecimal is>; in this case the method will receive'62'or'x3E'. This method is only called if convert_charrefs is 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)¶
このメソッドは 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
The content of elements like script and style is returned as is,
without further parsing:
>>> 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
Attribute names are converted to lowercase, quotes from attribute values removed,
and None is returned as value for empty attributes (such as 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 : >
Feeding incomplete chunks to feed() works, but
handle_data() might be called more than once
if convert_charrefs is 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