プログラミング

BeautifulSoup4によるスクレイピング【Python】

スクレイピングでよく使われるPythonライブラリの「BeautifulSoup」の使い方を紹介します。

BeautifulSoupはデフォルトのPythonライブラリではないので、まずインストールする必要があります。

Python3であれば次のようにインストールが可能です。

pip3 install beautifulsoup4

ここではBeautifulSoup4(bs4とも言う)を使います。

なお、BeautifulSoupに限ったことではないですが、デフォルトではないPythonライブラリをインストールする際は、仮想環境を作っておくのが望ましいです。その方がプロジェクトごとにどのライブラリを使っているか管理しやすいですし、グローバルにインストールしていると、ライブラリが干渉するなど不都合があるからです。

BeautifulSoup4がインストールできたら、実際に使ってみます。

from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen(‘https://kubogen.com/’)
bs = BeautifulSoup(html.read(), ‘html.parser’)
print(bs.h1)

BeautifulSoupライブラリでよく使われるBeautifulSoupオブジェクトを使っています。

また、BeautifulSoupの他に標準ライブラリのurllibからurlopen関数もインポートしています。

BeautifulSoupオブジェクトを作るには「html.read()」と「’html.parser’」の2つの引数を渡しました。

bs = BeautifulSoup(html.read(), ‘html.parser’)

第一引数の「html.read()」はオブジェクトのHTMLテキストです。

BeautifulSoupではurlopenで返されたファイルオブジェクトを直接使うことができるので、.read()を呼び出さずに、次のように書いても問題ありません。

bs = BeautifulSoup(html, ‘html.parser’)

第二引数はBeautifulSoupがオブジェクトを作るのに使うパーサです。

パーサはインストールが不要な「html.parser」を使うことが多いと思いますが、他にも「lxml」や「html5lib」などを指定することができます。

「lxml」や「html5lib」にはそれぞれ次のような特徴があります。

  • lxml・・・整っていないHTMLでもうまくパースできるがインストールが必要
  • html5lib・・・lxmlよりもHTML構文に問題があってもうまく読み込めるがインストールが必要で、html.parserやlxmlより遅い

「html.parser」はPython3に組み込まれているパーサでインストールする必要がないので、一番使い勝手がいいと思います。

urlopenで開いたWebページのHTMLコンテンツがBeautifulSoupオブジェクトに変換され、h1を抽出したので、次のように出力されます。

<h1 class=”site-title”>
<a href=”https://kubogen.com/” title=”KUBOGEN”>KUBOGEN</a>
</h1>

このようにたった5行のコードで簡単にスクレイピングができましたが、例外処理をするのがベターです。

スクレイピング時には対象のWebページが見つからなくて「404 Page Not Found」や「500 Internal Server Error」などのHTTPエラーが起きたり、サーバーが見つからないというケースがあります。

存在しないタグにアクセスしようとすると、BeautifulSoupはNoneオブジェクトを返しますし、NoneオブジェクトにアクセスしようとするとAttributeErrorが起きます。

なので、HTTPエラーのチェックやBeautifulSoupオブジェクトのタグにアクセスするたびに、タグが存在しているかチェックするのが望ましいです。

from urllib.request import urlopen
from urllib.error import HTTPError
from bs4 import BeautifulSoup

def getTitle(url):
  try:
    html = urlopen(url)
  except HTTPError as e:
    return None
  try:
    bs = BeautifulSoup(html.read(), ‘html.parser’)
    title = bs.body.h1
  except AttributeError as e:
    return None
  return title

title = getTitle(‘https://kubogen.com/’)
if title == None:
  print(‘Title could not be found’)
else:
  print(title)

最初のコードと同じ結果が出ますが、エラーをチェックして処理しているので、何か問題があった場合でも対処できます。

Leave a Comment