エンジニアの頭の中

トレードbotエンジニアが書く技術と投資のブログ

HTMLからタグを抽出!BeautifulSoupによるWebスクレイピング入門【Python】

f:id:mitsu3204:20180824013430j:plain

目次

WebスクレイピングとBeautifulSoup

Webスクレイピングとは、WebサイトのHTMLを解析して、ページに記載されているタグを抽出することです。

詳しくは、Wikipediaを見てもらったほうが良いかと思います。

ウェブスクレイピング - Wikipedia

Webスクレイピングでできること

Webスクレイピングの用途としては、Webサイトの情報を定期的に自動収集するスパイダー的なものや、Webサイトの操作を自動化して業務の効率化を図ったり、ページのテストに使ったりします。

import.ioのように、Webスクレイピングをサービスとして提供している企業もありますね。

ただ、Webスクレイピングによって情報を収集することを禁止しているWebサイトもあるので、自分でWebスクレイピングを行う場合は注意しましょう。

BeautifulSoupはWebスクレイピングのためのPythonライブラリ

BeautifulSoupとは、HTMLやXMLを解析してタグの抽出を行うためのPythonライブラリです。

Beautiful Soup: We called him Tortoise because he taught us.

PythonでWebスクレイピングをする場合は、まず間違いなくBeautifulSoupを使うでしょう。シンプルに扱うことができて、非常に便利なライブラリです。

BeautifulSoupの使うための準備

BeautifulSoupをインストールする

pipを使って「BeautifulSoup 4」というライブラリをインストールします。名前はbeautifulsoup4となっています。

$ pip install beautifulsoup4

※お使いの環境によってはpipではなくpip3の場合もあります。

BeautifulSoupの現在のバージョンは、4.6系です。

requestsをインストールする

もう一つライブラリをインストールします。「requests」といって、HTTP通信を行うためのライブラリです。

Pythonには、urllibというモジュールがあり、このモジュールを使ってHTTP通信を行うコードを書くことは可能なのですが、requestsを使うと、urllibより簡単にコードを書くことができます。

HTMLのタグスクレイピングに限らず、HTTP通信を伴う様々な処理で活躍するライブラリです。便利なのでインストールしておきましょう。

$ pip install requests

BeautifulSoupの使い方

HTMLページを解析してみましょう。処理の流れとしては、以下のとおりです。

  1. HTTP通信を行ってHTMLを取得
  2. 取得したHTMLを解析してタグを抽出

requestsでWebページを取得する

BeautifulSoupの公式ページにアクセスしてみます。

requestsを使用してWEBページを取得するには、以下のコードを書きます。

import requests

res = requests.get('https://www.crummy.com/software/BeautifulSoup/')

これは、GETメソッドで指定したURLのWEBページを取得しており、戻り値を格納している変数resには、HTTPレスポンスの情報が詰まっています。

HTMLの内容は、res.textに格納されています。以下のようにprint関数でres.textを表示してみましょう。

# レスポンスのHTMLの内容を出力する
print(res.text)

実行結果

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>Beautiful Soup: We called him Tortoise because he taught us.</title>
<link href="mailto:leonardr@segfault.org" rev="made"/>
<link href="/nb/themes/Default/nb.css" rel="stylesheet" type="text/css"/>
<meta content="Beautiful Soup: a library designed for screen-scraping HTML and XML." name="Description"/>
<meta content="Markov Approximation 1.4 (module: leonardr)" name="generator"/>
<meta content="Leonard Richardson" name="author"/>

... 省略 ...

このとおり、requestsを使うと簡単にHTMLを取得することができます。

HTMLのタグ構造を解析する

では、実際にHTMLのタグを抽出してみたいと思います。

先ほどのコードに、BeautifulSoupを使ってHTMLタグを解析するためのコードを書き足します。

import requests
from bs4 import BeautifulSoup

res = requests.get('https://www.crummy.com/software/BeautifulSoup/')
bs = BeautifulSoup(res.text, 'html.parser')

from bs4 import BeautifulSoupによって、bs4モジュールからBeautifulSoupオブジェクトをimportしています。

bs = BeautifulSoup(res.text, 'html.parser’)で、requestsで取得したレスポンスの内容(HTML)を渡して、BeautifulSoupオブジェクトを作成しています。

BeautifulSoupオブジェクトを作成する際に、解析対象がHTMLなのであれば、第二引数でhtml.parserとHTMLのパーサーを指定する必要があります。

指定したタグを取得する

HTML内のタグの内容を取得するにはbs.titleのようにBeautifulSoupオブジェクトに続けて.タグ名と記述します。

print(bs.title)

上記のコードを実行すると、titleタグの内容が出力されます。

実行結果

<title>Beautiful Soup: We called him Tortoise because he taught us.</title>

タグが入れ子構造になっている場合は、取得結果には子タグの内容も含まれます。

bs.headのように書いてheadタグの内容を取得すれば、headタグの入れ子となっているmetaタグやtitleタグなどがまとめて取得できます。

print(bs.head)

実行結果

<head>
<meta charset="utf-8"/>
<title>Python - Wikipedia</title>
<script>document.documentElement.className = document.documentElement.className.replace( /(^|\s)client-nojs(\s|$)/, "$1client-js$2" );</script>

... 省略 ...

</head>

bs.xxxxとタグ名を指定した際に、該当のタグ名が解析したHTMLページにtitleタグが存在しない場合は、Noneが返されます。

print(type(bs.title))とtype関数でbs.titleの調べるとわかりますが、このbs.タグ名で取得したオブジェクトは、bs4.element.Tagクラスのオブジェクトです。

タグのボディを抽出する

HTMLタグを解析して、何かしらの処理を行う際には、HTMLタグは除去して中身のボディ部のみが欲しいという場合があります。

ボディ部のみを取得する場合は、bs.title.textように書きます。

print(bs.title.text)

これを実行すると、titleタグの先頭の開始タグと末尾の終了タグに囲まれたボディ部のテキストのみを取得できます。

実行結果

Beautiful Soup: We called him Tortoise because he taught us.

タグの属性を抽出する

タグの属性(class、idなど)を抽出する場合は、Tagオブジェクトからgetメソッドを呼び出します。

bs.meta.get('content')

実行結果

text/html; charset=utf-8

HTML内の元のmetaタグは<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>という内容なのですが、content属性の値が抽出され、text/html; charset=utf-8と表示されました。

タグの属性は、attrsという辞書型のフィールドに格納されています。getメソッドは、このattrsフィールドを参照しているにすぎません。

# 以下の二つのコードは同じことをしている
bs.meta.get('content')
bs.meta.attrs['content']

よって、タグが持つ各属性にまとめてアクセスする必要がある場合は、getメソッドではなくattrsフィールドを使うことができます。

for k, v in bs.meta.attrs.items():
    print(k, v)

複数のタグを抽出する

htmlタグやtitleタグは、一つのHTMLページ内に一つしか存在しないものですが、その他のタグは多くの場合、一つのHTMLページ内に複数個の同じタグが存在するものです。

先ほどのbs.タグ名のような書き方では、複数のタグは対応できず、HTML内に同様の名前のタグが複数存在する場合は、先頭の一つ目が返さるだけです。

複数のタグをまとめて取得するには、以下のようにfind_allメソッドを使います。引数にはタグ名を指定します。

以下は、HTML内に存在する全てのaタグ(アンカー)を取得します。

print(bs.find_all('a'))

実行すると、find_allメソッドの引数に指定したタグの内容をまとめて取得することができます。

実行結果

[<a href="bs4/download/"><h1>Beautiful Soup</h1></a>, <a href="#Download">Download</a>, <a href="bs4/doc/">Documentation</a>, 

... 省略 ...

]

find_allメソッドの戻り値はlistではなく、listを継承したbs4.element.ResultSetのオブジェクトとして返されます。

listと同じように扱えるので、戻り値をそのままループで処理することも可能です。

# 全てのaタグを取得して、href属性があれば、その値(リンク先のURL)を出力する
for a in bs.find_all('a'):
    if 'href' in a.attrs:
        print(a.get('href'))

実行すると、以下のようにaタグのリンク先URL一覧が出力されます。

実行結果

bs4/download/
#Download
bs4/doc/
#HallOfFame
https://code.launchpad.net/beautifulsoup
https://bazaar.launchpad.net/%7Eleonardr/beautifulsoup/bs4/view/head:/NEWS.txt
https://groups.google.com/forum/?fromgroups#!forum/beautifulsoup

... 省略 ...

BeautifulSoupオブジェクトからは、findというメソッドも呼び出し可能です。findメソッドも呼び出し方はfind_allと同様で、find(タグ名)のように使いますが、bs.タグ名のようにHTMlの解析結果から最初の一つ目のタグのみを返すものです。

タグの属性を条件としてタグを抽出する

find_allメソッドでタグを抽出するための条件は、タグ名だけではありません。 タグの属性情報も抽出条件として指定できます。

例えば、HTML内のaタグのうち、content属性の値がtrueのものだけを抽出したいのであれば、find_allメソッドのattrs引数に以下のように辞書形式で、属性の名前と値を指定します。

for meta in bs.find_all(name='meta', attrs={'name': 'author'}):
    print(meta)

※わかりやすさのために引数名を記載しています。記載しなくても動きます。

実行すると、metaタグのうち、name属性がauthorの値のものだけが抽出できます。

実行結果

<meta content="Leonard Richardson" name="author"/>

attrs引数には、辞書形式で複数の属性を指定できるので、さらに厳密に属性を指定して抽出するタグを絞り込むことが可能です。

最後に

PythonとBeautifulSoupを使うと、HTMLを解析してタグを抽出するということが、簡単に実現できるのがおわかり頂けたと思います。

また次の機会にWebスクレイピングについてもっと深掘りした記事も書いてみたいと思います。

最近は、Webスクレイピングに関する書籍も増えたと感じますが、以下の書籍は、オライリー社から出ているもので、Webスクレイピング本に関するオススメ本です。

PythonによるWebスクレイピングをAmazonで見る

Webスクレイピングをネタに一冊本がかけちゃうんです。本の中でもBeautifulSoupを使っていて、Webスクレイピングに興味があるならこれで勉強しておくと良いと思います。普通に面白い本です。