02. BeautifulSoup

図解!Beautiful SoupでWEBスクレイピング徹底解説!(select、find、find_allの使い方、インストールなど)

更新日:

Beautiful Soupとは、HTMLやXMLファイルからデータを取得し、解析するPythonのWEBスクレイピング用のライブラリです。インターネット上に公開されているWEBサイトでは広くHTMLやXMLが使われており、これらの情報の取得や解析に、大変便利なライブラリです。
 
Pythonでは、Beautiful Soupを利用して、簡単にWEBサイトからデータを自動的に取得することができます。
 
Beautiful Soupは、

  • 情報収集の為にニュースサイトやブログから、自動的にデータを取得し保存したい。
  • 製品の価格情報を取得して、トレンドを把握し価格設定に利用したい。
  • WEBサイトから統計情報や他社のIR情報を取得し、競合分析、マーケットリサーチに活用したい。

という場合に利用すると便利です。
 
ここではまず、Beautiful Soupというライブラリの基本となる使い方を確認していきましょう。
 
 

著書紹介(清水 義孝)

好評発売中!!

Beautiful Soupを使うための準備(インストール)

Beautiful Soupは、標準ではインストールされていませんので、pipやcondaを利用して別途インストールする必要があります。
 
pipを利用してインストールする場合は、以下のコマンドを入力してください。

pip install beautifulsoup4

 
またcondaを利用してライブラリをインストールする場合は、次のコマンドを入力してください。

conda install beautifulsoup4

 
 
またBeautiful Soup自体はHTMLファイルやXMLファイルを解析するライブラリで、ファイルデータのダウンロードは行いません。Beautiful Soupでファイルを解析するには、ファイルデータをダウンロードする必要がありますので、必要なライブラリrequestsもインストールします。
 
requests をpipでインストールする場合は、次のコマンドを入力してください。

pip install requests

 
またcondaでインストールする場合は、次のコマンドを入力してください。

conda install requests

 
これでインストールは終わりました。次に、これらのライブラリを利用する前にはインポートしておく必要があります。

In [1]: import requests
...: from bs4 import BeautifulSoup

 
以上で、Beautiful Soupを使うための準備は終わりです。
 
 

著書紹介(清水 義孝)

好評発売中!!

Beautiful Soupに必要なrequestsの使い方

これからBeautiful Soupの基本となる使い方を紹介していきます。ここはでは、読売新聞オンライン(https://www.yomiuri.co.jp/) から記事を取得してみます。
 
まず今回は、メインページのトップニュースのタイトル(赤線で囲った箇所)とそのURLを取得したいと思います。

 
まずはrequestsを利用して、WEBサイトの情報をダウンロードします。変数urlを定義し、確認したいWEBサイトのアドレスを渡します。次に、requests.get()に対してurlを渡しています。request.get()で指定されたwebの情報を取得し、その結果は、変数resに格納します。

In [2]: url = 'https://www.yomiuri.co.jp'
...: res = requests.get(url)

 
試しに取得した内容を表示してみましょう。textで内容を確認することができます。

In [3]: res.text

 

Out[3]:

WEBサイトの大量の情報が取り込まれています。
 
 

著書紹介(清水 義孝)

好評発売中!!

Beautiful Soupの基本的な使い方

次に、この情報の中からトップニュースのタイトルとURLを取り出してみましょう。そのためには、BeautifulSoup()を用いて、ダウンロードした情報の解析が必要になります。
 
BeautifulSoup()の記述方法は以下です。

BeautifulSoup(解析対象のHTML/XML, 利用するパーサー)

1つ目の引数には、解析対象のHTML/XMLを渡します。
2つ目の引数として解析に利用するパーサー(解析器)を指定します。

パーサー引数での指定方法特徴
Python’s html.parser“html.parser”追加ライブラリが不要
lxml’s HTML parser“lxml”高速に処理可
lxml’s XML parser“xml”XMLに対応し、高速に処理可
html5lib“html5lib”正しくHTML5を処理可

この中でも、今回はPythonの標準ライブラリに入っており、追加でライブラリのインストールが不要なPython’s html.parserを利用します。
 
BeautifulSoup()に先ほど取得したWEBサイトの情報とパーサー"html.parser"を渡してあげます。

In [4]: soup = BeautifulSoup(res.text, "html.parser")

 
これらの情報を用いてBeautiful SoupではHTMLを解析していきますが、必要な箇所を解析するために、該当箇所を指定、検索する方法がいくつかあります。その中で、利用しやすいものは次の2つになります。

  • 1つ目は、selectメソッドにより、CSSセレクタで該当する箇所を指定する方法です。
  • 2つ目は、find、find_allメソッドにより、HTMLタグで該当する箇所を検索する方法です。

ここではまず、1つ目のselectメソッドによりCSSセレクタで指定する方法を確認していきましょう。
 
 

Beautiful Soupにおけるselectメソッドの使い方(CSSセレクタによる抽出)

ということで、次に、WEBサイトの取得したい箇所を指定して情報を抽出していきます。そのためには、WEBサイトから該当箇所を示すCSSセレクタという情報(住所のようなもの)を取り出します。CSSセレクタは、HTMLから処理対象とする要素を選択するのに利用します。
 
CSSセレクタを調べるためには、WEBブラウザとしてGoogle Chromeを使うと非常に便利です。インストールされておられない場合は、インストールをお勧めします。
 
Google Chromeのインストールは、こちらのリンクをご参照ください。
https://support.google.com/chrome/answer/95346?co=GENIE.Platform%3DDesktop&hl=ja
 
Google Chromeの準備が整いましたら、Google Chromeで読売新聞オンラインのページを開きます。メインページのトップニュースのタイトルにマウスのカーソルを当て、右クリックします。するとメニューが表示されますので、その中から「検証」を選択します。

 
すると、右側にウィンドウが現れ、HTMLが表示されます。先ほどのトップニュースのタイトルに該当する箇所にカーソルが当たった状態で、右クリックします。またメニューが表示されますので、Copy → Copy selectorを選択します。

 
このようにしてコピーしたCSSセレクタをメモ帳に貼り付けます。すると次のようなCSSセレクタが表示されます。これがトップニュースに該当する箇所のCSSセレクタになります。

body > div.layout-contents > div.layout-contents__main > div > div.home-main-news-organization.p-category-latest > section > ul > li:nth-child(1) > article > div.p-list-item__inner > h3 > a

 
これを用いて、Beautiful Soupで解析を進めていきますが、1つサポートされていないCSSセレクタ、nth-childがあります(該当箇所の背景色を変えています)。nth-childをnth-of-typeに変更する必要があります。
 
変更後

body > div.layout-contents > div.layout-contents__main > div > div.home-main-news-organization.p-category-latest > section > ul > li:nth-of-type(1) > article > div.p-list-item__inner > h3 > a

 
このようにして取得したCSSセレクタをsoup.select()に渡します。戻り値は、変数elemsに格納します。

In [5]: elems = soup.select('body > div.layout-contents > div.layout-contents__main > div > div.home-main-news-organization.p-category-latest > section > ul > li:nth-of-type(1) > article > div.p-list-item__inner > h3 > a')

ここまでがWEBサイトから指定した箇所の情報を単純に取得する一連の処理になります。
 
これらの取得した情報を表示してみましょう。変数elemsの最初の要素を表示してみます。

In [6]: elems[0]
Out[6]: <a href="https://www.yomiuri.co.jp/national/20190814-OYT1T50159/">台風10号、太平洋側で1200ミリ超す大雨も</a>

 
指定したトップニュースのタイトルやリンクが表示されました。但し、HTMLのタグが混在しており、見やすい状態とは言えません。
 
次にcontentsを利用して内容を表示してみます。

In [7]: elems[0].contents[0]
Out[7]: '台風10号、太平洋側で1200ミリ超す大雨も'

トップニュースのタイトルだけを取り出すことができました。
 
今度はリンクのURLだけを取得したいと思います。リンクが含まれているタグhrefの内容だけを抽出するattrs['href']を利用します。

In [8]: elems[0].attrs['href']
Out[8]: 'https://www.yomiuri.co.jp/national/20190814-OYT1T50159/'

 
このようにして、Beautiful Soupを利用して指定したトップニュースのタイトルやリンクを取得することができました。
 
 

著書紹介(清水 義孝)

好評発売中!!

Beautiful Soupにおけるfind、find_allメソッドの使い方(HTMLタグによる抽出)

前回はCSSセレクタを利用して情報を抽出しましたが、次は、HTMLタグで該当する箇所を検索する方法を試してみましょう。
 
ここはでは、yahoo(https://www.yahoo.co.jp/) から記事を取得してみます。今回は、メインページのトップニュースから、タイトル(赤線で囲った箇所)とそのURLの組み合わせの一覧を取得したいと思います。

 
前回同様、requestsを利用して、WEBサイトの情報をダウンロードします。変数urlを定義し、確認したいWEBサイトのアドレスを渡します。次に、requests.get()に対してurlを渡しています。request.get()で指定されたwebの情報を取得し、その結果は、変数resに格納します。

In [1]: url = 'https://www.yahoo.co.jp/'
...: res = requests.get(url)

 
BeautifulSoup()に先ほど取得したWEBサイトの情報とパーサー"html.parser"を渡してあげます。

In [2]: soup = BeautifulSoup(res.text, "html.parser")

 
これらの情報を用いてBeautiful SoupではHTMLを解析していきますが、該当箇所を指定、検索する方法の中で、今回は、HTMLタグで該当する箇所を検索する方法を利用します。
 
Beautiful Soupでは、HTMLタグで該当する箇所を検索するメソッドには次のようなものがあります。

メソッド引数説明
find()検索するHTMLタグ引数に一致する 最初の1つの 要素を取得します。
find_all()検索するHTMLタグ引数に一致する 全ての 要素を取得します。

 
まずは該当する箇所のHTMLタグを確認します。ブラウザでyahooのページを開きます。(ここでは、Google Chromeの例を載せていますが、他のブラウザでも確認できます。)
 
メインページのトップニュースのタイトルにマウスのカーソルを当て、右クリックします。するとメニューが表示されますので、その中から「検証」を選択します。

 
すると、右側にウィンドウが現れ、HTMLが表示されます。先ほどのトップページのニュースは、htmlのタグで<a href=”url”>…</a>のように記載されているようです。
 
タグ<a>は、リンクの開始点と終了点を指定するタグです。リンクの開始点ではhref属性でリンク先を指定しています。

ここで先ほどのメソッドを試してみましょう。まずはfind()に引数”a”を渡すと、

In [3]: elems = soup.find("a")
...: elems
Out[3]: <a href="https://www.yahoo-help.jp/"><nobr>ヘルプ</nobr></a>

タグ<a>が含まれる内容が表示されましたが、欲しい情報ではないようです。find()では、引数で渡されたタグで検索してヒットした、最初の1つの 要素を取得しますので、その内容が表示されているようです。
 
次に、find_all()に引数”a”を渡して、検索してみます。

In [4]: elems = soup.find_all("a")
...: elems
Out[4]:

今度は、タグ<a>が含まれる全ての要素が表示されました。ここから必要な情報だけに絞り込む必要があるようです。
 
どのようにして絞り込めば良いのでしょうか?先ほど表示された内容をよく見てみると、トップニュースに該当する箇所は全て、URLに”news.yahoo.co.jp/pickup”が含まれているようです。これが利用できそうです。

 
ということで、URLに”news.yahoo.co.jp/pickup”が含まれているとう条件でさらに絞り込んでいきましょう。
 
ここで文字列のパターンで検索できるライブラリreをインポートします。

In [5]: import re

 
ライブラリreのcompile()を利用して、href=re.compile("news.yahoo.co.jp/pickup") をfind_all()の引数として渡します。ここでは、href属性の中で"news.yahoo.co.jp/pickup"が含まれているもののみ全て抽出しています。そして抽出した結果を表示すると、

In [6]: elems = soup.find_all(href=re.compile("news.yahoo.co.jp/pickup"))
...: elems
Out[6]:

表示したいトップニュースの箇所に絞り込んで情報を表示することができました。
 
後は、ここからURLとタイトルを抽出して一覧表示するだけです。ここからは前回学習した内容を活かすことができそうです。
 
まずは1つ目のニュースのタイトルを表示してみます。contentsを使えばよかったですね。

In [7]: elems[0].contents[0]
Out[7]: '台風10号 北日本で激しい雨か'

トップニュースの1つ目のタイトルだけを取り出すことができました。
 
今度はリンクのURLだけを取得したいと思います。リンクが含まれているタグhrefの内容だけを抽出するattrs['href']を利用します。

In [8]: elems[0].attrs['href']
Out[8]: 'https://news.yahoo.co.jp/pickup/6333479'

 
同様に、2つ目のニュースも取得してみましょう。リストelemsの2つ目の要素を表示するよう、elems[0]からelems[1]に変更します。

In [9]: elems[1].contents[0]
Out[9]: '北 韓国と「再び対座せず」'

 
2つ目のニュースのURLも同様に、elems[0]からelems[1]に変更すると表示されました。

In [10]: elems[1].attrs['href']
Out[10]: 'https://news.yahoo.co.jp/pickup/6333491'

 
このようにしてリストelemsに格納されている全ての要素のcontensとhref属性を取得すれば、タイトルとURLの一覧を表示することができます。全ての要素の表示はfor文を使って次のように書きます。

In [11]: for elem in elems:
....:        print(elem.contents[0])
....:        print(elem.attrs['href'])
Out[11]:

このようにして、yahooのトップページからニュースのタイトルとURLの一覧を取得することができました。

 
 

-02. BeautifulSoup

Copyright© AI-interのPython3入門 , 2019 All Rights Reserved.