Python: lxmlを使って高速にaタグを取得する方法

2012年2月18日

PythonでXML/HTMLをパースする場合、

    DOMベースのBeautifulSoup



    SAXベースのlxml

の大きく2つが存在しています。

前者は以前このブログでも紹介していますので、ご覧下さい。DOMベースなので気軽にパース処理することができる反面、少々処理が重いです。

一方後者は、XPATHと呼ばれる問い合わせ言語(まぁ、SQLのようなもんです)をある程度理解する必要はありますが、メモリもそんなに使わず大変高速なため、phactoryではよく使っています。

今日はこのlxmlを使ってタグ抽出する方法を紹介します。


lxmlはデフォルトライブラリとしてビルトインされていますので、特にインストール作業を行う必要はありません。

機能としては

 

  • XML/HTMLをパース可能。
  • HTMLのタグの入れ子関係の修復機能あり。
  • SAXベースの高速なパース処理。
  • BeautifulSoupのlibxml2ベースでのサポート。

などなど、様々です。

ベースはlibxml2で、BeautifulSoup API群も使えるので嬉しい限りですね。

 

まずはともかく、ソースサンプルを見てみましょう。

aタグを抽出する方法です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import copy
from lxml import etree
dom = etree.fromstring(html_str, parser=etree.HTMLParser())
enums = dom.xpath('//div')

# DIV要素中のaタグを取得
for e in enums:
    ec = copy.copy(e)
    atags = ec.xpath('//a')
    for a in atags:
        print a.attrib['href']

xpath(xxx)で、HTML中の任意のタグを指定します。

指定方法は、XPATH言語を用いて、HTML上の任意のパスを指定します。

上記の例だと「//div」と「//a」なので、任意のパス列でdivとaを含むような部分HTMLをそれぞれenumsatagsにて取得していることになります。

e.xpath('//a')とすると、html_str全体からaタグを取得してしまうので、上記のようにコピーオブジェクトに対して検索する部分もミソです。