Python: lxmlを使って、タグを巡回する方法

2012年2月19日

HTMLの分析を行う際、タグを巡回する必要がありますがそんなとき、lxmlを使うと便利です。

lxmlでは、タグの入れ子関係が壊れたHTMLの修復も自動で行ってくれる機能がありますのでユーザは細かいことを気にする必要はありません。この修復機能のおかげで、入れ子の修復(閉じ括弧がないタグは閉じ括弧を付与)を行ってくれるため、HTMLをツリーとして、つまりDOMツリーとして捉えることができるようになるのです。

DOMツリーだから何やねん!という方は読み飛ばしてもらっていいのですが、ツリーであるおかげで親ノード(親タグ)をたぐったり、兄弟ノード(兄弟タグ)をたぐったりが簡単にできるようになるのですね。lxmlってすばらしい。

木を巡回する手法はいろいろとありますが、今日は深さ優先で巡回する手法をみてみましょう。

lxml.etree.iterwalk()を使うと、深さ優先でHTMLのタグを巡回することができます。

1
2
3
4
5
6
7
from lxml import etree

for d in etree.iterwalk(etree.fromstring(html, parser=etree.HTMLParser()), events=("start", "end",)):
   if ( d[0] == "start" ):
       print "<%s>" % d[1].tag,
   elif ( d[0] == "end" ):
       print "</%s>" % d[1].tag,

 

「events=("start", "end")」と指定することで、開始タグと終了タグを見つけるたびに以下のように個別に処理を行うことができます。その時のタグ名はlxmlのノード型ですので、「tag」メンバでアクセスできます。