[Python] Beautiful SoupでHTMLやXMLをparseしよう
Beautiful Soup はHTMLやXMLをparseしてくれるパーサーライブラリです。でも、Beautiful Soupは単なるパーサーじゃなくてちょっと賢い奴なんです。
今回、このBeautiful Soupのドキュメントを翻訳しました。
http://www.tdoc.info/beautifulsoup/
下に軽く紹介していますが、詳しくはこのドキュメントをご覧ください。
Beautiful Soupをざっくり紹介
Beautiful Soupがどういうやつかって?例えばこんなHTMLがあったとしましょう。
<HTML>
<body>
改行<br>
したいよね
<br/>
<! --あれ、空白が入ってるちょっと変なコメント-->
<p>
bodyが閉じてないよ?
</html>
結構変なHTMLですよね。でも、巷にはこういうのも結構あるんです。で、これをtest1.htmlだとします。これをこんな感じのスクリプトでパースしてみると、
soup = BeautifulSoup(open("test1.html"))
print soup.prettify()
こうなります。
<html>
<body>
改行
<br />
したいよね
<br />
<!--あれ、空白が入ってるちょっと変なコメント-->
<p>
bodyが閉じてないよ?
</p>
</body>
</html>
他にも、
<html>
<form>
<table>
<td><input name="input1">一行目二列目
<tr><td>二行目
</form>あれ、テーブル閉じてないよ?
<td>こっちは?
</html>
を
<html>
<form>
<table>
<td>
<input name="input1" />
一行目二列目
</td>
<tr>
<td>
二行目
</td>
</tr>
</table>
</form>
あれ、テーブル閉じてないよ?
<td>
こっちは?
</td>
</html>
という感じにしてくれます。
インストール
ふつーpipですよねー。
% pip install beautifulsoup
使い方
まずはimportします。
from BeautifulSoup import BeautifulSoup # HTMLの場合こっち
from BeautifulSoup import BeautifulStoneSoup # XMLの場合こっち
import BeautifulSoup # 全部の場合これ
その後、BeautifulSoupコンストラクタを作って、あとはこれを使います。
soup = BeautifulSoup(html_string)
タグを検索
例えば、こういうHTMLドキュメントがあったとします。
<html>
<h1>H1です</h1>
段落
<p>
ですよ<br/>
</p>
<table>
<tr id="tr-1">閉じてないけどtr-1です<td>td-1-1</td><td>td-1-2
<tr id="tr-2">tr-2です<td class="td">td-2-1</td><td>td-3
</html>
タグはタグの名前で検索できますし、nextSiblingとかを使って順々にたどることも出来ます。もちろんforで回すことも出来ます。
parentで上に、contentsで下に、nextSiblingとprevSiblingで同じ階層にたどる、という感じでしょうか。
soup = BeautifulSoup(doc)
print(soup.h1) # h1を表示
print("-------------------------------")
print(soup.table.td) # <table><td>の最初を表示
print("-------------------------------")
print(soup.table.tr) # <table><tr>の最初表示
print("-------------------------------")
tr1 = soup.table.tr
print(tr1.nextSibling) # tr-1のnextSibling
print("-------------------------------")
print(tr1.nextSibling["id"]) # tr-2のid属性
print("-------------------------------")
print(tr1.nextSibling.contents[1]["class"]) # tr-2の子のtdのclass属性
print("-------------------------------")
とすると、こう出ます。
<h1>H1です</h1>
-------------------------------
<td>td-1-1</td>
-------------------------------
<tr id="tr-1">閉じてないけどtr-1です<td>td-1-1</td><td>td-1-2
</td></tr>
-------------------------------
<tr id="tr-2">tr-2です<td class="td">td-2-1</td><td>td-3
</td></tr>
-------------------------------
tr-2
-------------------------------
td
検索
パースしたツリーを検索できます。
print(soup.findAll('td')) # tdを全部見つけてきます。
print("-------------------------------")
import re
print(soup.findAll(re.compile('^t'))) # tで始まるタグを全部持ってきます
print("-------------------------------")
[<td>td-1-1</td>, <td>td-1-2
</td>, <td class="td">td-2-1</td>, <td>td-3
</td>]
-------------------------------
[<table>
<tr id="tr-1">閉じてないけどtr-1です<td>td-1-1</td><td>td-1-2
</td></tr><tr id="tr-2">tr-2です<td class="td">td-2-1</td><td>td-3
</td></tr></table>, <tr id="tr-1">閉じてないけどtr-1です<td>td-1-1</td><td>td-1-2
</td></tr>, <td>td-1-1</td>, <td>td-1-2
</td>, <tr id="tr-2">tr-2です<td class="td">td-2-1</td><td>td-3
</td></tr>, <td class="td">td-2-1</td>, <td>td-3
</td>]
-------------------------------
他にも
Beautiful Soupはこんなこともできます。
- 属性の値を入れ替えたり、新しい属性を付けたりする
- あるエレメントを別なエレメントに置き換える
- UnicodeDammitというクラスを使ってエンコーディングを判定する
- HTMLの実体参照を対応するユニコード文字に変換する
詳しくは翻訳したドキュメントを参照してください。