はじめに
BeautifulSoup は、HTML や XML のパーサであり、Webスクレイピングで使用することができる。
また、同じようにスクレイピングをする他のライブラリには、PyQueryがあるが、そちらは以下の記事を参照したい。
[Python] PyQuery でWebスクレイピングをしてみる
本稿では、BeautifulSoup4 を使用して HTML から情報を抽出する方法を説明する。
インストール
% pip install beautifulsoup4
使用するhtml
from bs4 import BeautifulSoup
html = """
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<h1 id="test-id" class="test-class">Test Text</h1>
<a href="http://zombie-hunting-club.com">ゾンビ狩りクラブ</a>
<ul>
<li>item1</li>
<li>item2</li>
<li>item3</li>
</ul>
<div id="div1">
<p class="p1">pタグ内のテキスト1</p>
</div>
<div id="div2">
<p class="p2">pタグ内のテキスト2</p>
</div>
</body>
</html>
"""
今回は直接文字列に書き込んでいるが、どっかのサイトから持ってくる場合は、Requests や selenium + Phantom.js なんかで HTML を取得する。
インスタンスの生成
以下でインスタンスを生成することができる。
また、prettifyメソッドを使用して html を整形して表示することができる。
soup = BeautifulSoup(html, "html.parser")
print(type(soup))
# <class 'bs4.BeautifulSoup'>
print(soup.prettify()) # htmlを整形して表示
# <!DOCTYPE html>
# <html>
# <head>
# </head>
# <body>
# <h1 class="test-class" id="test-id">
# Test Text
# </h1>
# <a href="http://zombie-hunting-club.com">
# ゾンビ狩りクラブ
# </a>
# <ul>
# <li>
# item1
# </li>
# <li>
# item2
# </li>
# <li>
# item3
# </li>
# </ul>
# <div id="div1">
# <p class="p1">
# pタグ内のテキスト1
# </p>
# </div>
# <div id="div2">
# <p class="p2">
# pタグ内のテキスト2
# </p>
# </div>
# </body>
# </html>
検索メソッド
検索メソッドには、以下がある。
- find_all() と find()
- select()
- find_all_next() と find_next()
- find_all_previous() と find_previous()
- find_next_siblings() と find_next_sibling()
- find_previous_siblings() と find_previous_sibling()
- find_parent() と find_parents()
find() と find_all()
スクレイピングを行う上では、この2つのメソッドがメインになる。
find() と find_all() の書式は同じで、find()はマッチしたものの最初の一つを返すが、find_all()はすべてをリストで返す。
また、find_all() メソッドのショートカットである soup() も使用することができる。
書式は以下になる。
find_all(name, attrs, recursive, string, limit, **kwargs)
find(name, attrs, recursive, string, **kwargs)
要素の検索
タグから検索
print(soup.find("p"))
# <p class="p1">pタグ内のテキスト1</p>
また、タグなら以下でも検索することができる。
print(soup.p)
# <p class="p1">pタグ内のテキスト1</p>
マッチしたものすべて返すようにするには、以下のようにする。
print(soup.find_all("p"))
# [<p class="p1">pタグ内のテキスト1</p>, <p class="p2">pタグ内のテキスト2</p>]
もしくは、soup() を使用して以下のように検索することができる。
print(soup("p"))
# [<p class="p1">pタグ内のテキスト1</p>, <p class="p2">pタグ内のテキスト2</p>]
idから検索
idを指定して検索する方法は以下がある。
print(soup(id="test-id"))
# [<h1 class="test-class" id="test-id">Test Text</h1>]
print(soup.find_all(id="test-id"))
# [<h1 class="test-class" id="test-id">Test Text</h1>]
print(soup.find_all(attrs={"id":"test-id"}))
# [<h1 class="test-class" id="test-id">Test Text</h1>]
classから検索
print(soup.find_all(class_="test-class"))
# [<h1 class="test-class" id="test-id">Test Text</h1>]
URLから検索
print(soup.find_all(href="http://zombie-hunting-club.com"))
# [<a href="http://zombie-hunting-club.com">ゾンビ狩りクラブ</a>]
テキストから検索
print(soup.find_all(string="pタグ内のテキスト2"))
# ['pタグ内のテキスト2']
複数条件を指定して検索
print(soup.find_all("h1", id="test-id", string="Test Text", attrs={"class":"test-class", "id":"test-id"}))
# [<h1 class="test-class" id="test-id">Test Text</h1>]
取得
タグ名を取得
print(soup.find(class_="p1").name)
# p
id や class, URL などの属性を取得
getメソッドで取得することができる。
print(soup.div.get("id"))
# div1
print(soup.p.get("class"))
# ['p1']
print(soup.a.get("href"))
# http://zombie-hunting-club.com
テキストを取得
print(soup.a.string)
# ゾンビ狩りクラブ
print(soup.find(class_="p2").string)
# pタグ内のテキスト2
selectメソッド
selectメソッドを使用すれば、以下のようにcssセレクタのように検索が行える。
print(soup.select("div > .p2"))
# [<p class="p2">pタグ内のテキスト2</p>]
その他のメソッド
find_all_next() と find_next()
find_all_next(name, attrs, string, limit, **kwargs)
find_next(name, attrs, string, **kwargs)
要素以降の指定した要素を検索する。
h1 = soup.h1
print(h1)
# <h1 class="test-class" id="test-id">Test Text</h1>
print(h1.find_all_next("p"))
# [<p class="p1">pタグ内のテキスト1</p>, <p class="p2">pタグ内のテキスト2</p>]
find_all_previous() と find_previous()
find_all_previous(name, attrs, string, limit, **kwargs)
find_previous(name, attrs, string, **kwargs)
find_all_next() と find_next() の要素以前を検索するバージョン。
find_next_siblings() と find_next_sibling()
find_next_siblings(name, attrs, string, limit, **kwargs)
find_next_sibling(name, attrs, string, **kwargs)
要素以降の同じ深さにある指定した要素を検索する。
h1 = soup.h1
print(h1)
# <h1 class="test-class" id="test-id">Test Text</h1>
print(h1.find_next_siblings("div"))
# [<div id="div1">
# <p class="p1">pタグ内のテキスト1</p>
# </div>, <div id="div2">
# <p class="p2">pタグ内のテキスト2</p>
# </div>]
h1 = soup.h1
print(h1.find_next_siblings("li"))
# []
find_previous_siblings() と find_previous_sibling()
find_previous_siblings(name, attrs, string, limit, **kwargs)
find_previous_sibling(name, attrs, string, **kwargs)
find_next_siblings() と find_next_sibling() の要素以前を検索するバージョン。
find_parent() と find_parents()
find_parents(name, attrs, string, limit, **kwargs)
find_parent(name, attrs, string, **kwargs)
親要素を返す。
p = soup.find("p")
print(p)
# <p class="p1">pタグ内のテキスト1</p>
print(p.find_parents("div"))
# [<div id="div1">
# <p class="p1">pタグ内のテキスト1</p>
# </div>]
0件のコメント