Pythonの BeautifulSoup
というライブラリについてご紹介します。
import BeautifulSoup
BeautifulSoup はバージョン 3 までと現在最新のバージョン 4 とでパッケージ名が異なります。バージョン 4 では BeautifulSoup4 もしくは bs4 という名前になっています。
- バージョン 3: BeautifulSoup
- バージョン 4: bs4
今回はバージョン 3 を対象に述べていきます。ちなみに、バージョン 3 は Pyton 3 には対応していないため、 Python 3 で使うなら バージョン 4 の方を使うことになります。
バージョン 3 までの BeautifulSoup には大きく分けて 2 つのクラスが入っています。 BeautifulSoup
と BeautifulStoneSoup
です。
BeautifulSoup
: HTML 用BeautifulStoneSoup
: XML 用
(ちなみに、BeautifulSoupのバージョン4では BeautifulStoneSoup
は BeautifulSoup
に吸収され存在しません)。
基本的な使い方は HTML でも XML でも共通なので、今回は ElementTree
との対比で後者の BeautifulStoneSoup
の方だけを見ていきます。
XMLファイルの読み込み
from BeautifulSoup import BeautifulStoneSoup
XMLFILE = 'sample.xml'
f = open(XMLFILE, 'r')
soup = BeautifulStoneSoup(f.read())
f.close()
XML ファイルを読み込むには、通常のファイルオープンをしてテキストを抽出し、そこから BeautifulStoneSoup
インスタンスを生成します。
以下、 samle.xml
の中身は次のとおりという想定で進めます。
<post attrA="value A" attrB="value B">
<title>This is a title.</title>
<categories>
<!-- This is a comment. -->
<category term="Asia"/>
<category term="South America"/>
<category term="Europe"/>
</categories>
</post>
データの読み方
上のコードのとおり XML のおおもとのインスタンス soup
を生成したら、あとはツリーを辿ってデータを見ていきます。ツリーを辿るには主に次のふたつのメソッドを使います。
soup.find()
soup.findall()
BeutifulStoneSoup では各ノードを Tag
クラスのインスタンスとして保持します。各ノードの情報にアクセスするには主に次のアトリビュート・メソッドを使います。
tag.name
tag.string
tag.attrs
tag.get()
以下、いろいろ見ていきます。
print soup.__class__.__name__
# BeautifulStoneSoup と出力
上のコードで生成したsoupはBeautifulStoneSoupのインスタンスです。
print soup.find('category').__class__.__name__
print soup.find('category').name
print soup.find('category').get('term')
print soup.find('category').attrs
# 以下のとおり出力
# Tag
# category
# Asia
# [(u'term', u'Asia')]
tag.find(タグ名)
で子孫のノードにアクセスすることができます。各タグは Tag
クラスのインスタンスです。 name
にはそのタグ名が入っています。
get()
か attrs
でタグのアトリビュート情報にアクセスできます。読み出した文字列はすべてユニコードとなっています。
print soup.find('title').string
# 以下のとおり出力
# This is a title.
tag.string
にはそのタグ内の文字列が入っています。
es = soup.findAll('category')
for e in es:
print e.name, e.get('term')
# 以下のとおり出力
# category Asia
# category South America
# category Europe
tag.find(タグ名)
が最初に見つかった要素を 1 つだけ返すのに対し、 tag.findAll(タグ名)
は引っかかった要素をすべて返します。
es = soup.findAll('category', term='Europe')
for e in es:
print e.name, e.get('term')
# 以下のとおり出力
# category Europe
find()
findAll()
を使うときは、タグ名だけでなくアトリビュートも手がかりに検索することができます。この例ではアトリビュート term
の値が Europe
の要素を検索しています。
print soup.post.title.string
# 以下のとおり出力
# This is a title.
タグの親子関係をもとにデータを取得することも可能です。この例では soup
以下の post
タグの中にある一番最初の title
タグの中身を取得しています。
その他の機能
# 整形表示
print soup.prettify()
取得した XML を整形して表示するために、 prettify()
というメソッドが用意されています。
# 元データのエンコード
print soup.originalEncoding
元データの文字コードは、 originalEncoding
で確認することができます。
# 子要素を取得
print soup.post.categories.contents
# 以下のとおり出力
# [u'\n', u' This is a comment. ', u'\n', <category term="Asia"></category>, <category term="South America"></category>, <category term="Europe"></category>]
contents
を使えば、タグだけでなく、コメントなどの文字列も含めて子要素を取得することができます。ただ、元の XML データに空白や改行が入っていると、思わぬところでインデックスが変わってしまったりしてハマりがちですので、タグ要素だけに着目するのであれば、 find()
findAll()
などを使うのがよいかと思います。
以上です。
今回は取り上げませんでしたが、このほかにも BeautifulSoup には
- あるノードの隣のノードや親ノードを取得する機能
- XMLを編集する機能
なども備わっています。さらに詳しくは参考ページなどをご参照ください。
また、 BeautifulSoup のバージョン 3 までとバージョン 4 とでは互換性の無いところがあるのでその点にも注意が必要です。本記事の説明はバージョン 3 を対象としています。
インストール
pip
が入っていれば、コマンドラインから pip install beautifulsoup
でインストールできます( BeautifulSoup4 は pip install beautifulsoup4
です)。