Beautiful Soup(ビューティフル・スープ)とは、HTMLやXMLファイルからデータを取得し、解析するPythonのWEBスクレイピング用のライブラリです。インターネット上に公開されているWEBサイトでは広くHTMLやXMLが使われており、これらの情報の取得や解析に、大変便利なライブラリです。
Pythonでは、Beautiful Soupを利用して、簡単にWEBサイトからデータを自動的に取得することができます。
Beautiful Soupは、
- 情報収集の為にニュースサイトやブログから、自動的にデータを取得し保存したい。
- 製品の価格情報を取得して、トレンドを把握し価格設定に利用したい。
- WEBサイトから統計情報や他社のIR情報を取得し、競合分析、マーケットリサーチに活用したい。
という場合に利用すると便利です。
この記事ではチュートリアル形式で、Python3におけるBeautiful Soupの基本的な使い方を解説していきます。
- PythonのWEBスクレイピング用ライブラリとその違い(Selenium、BeautifulSoup、Requests)
- BeautifulSoup4と関連ライブラリのインストール
- BeautifulSoupの前に必要なRequestsを使ったデータの取得方法
- BeautifulSoupの基礎的な使い方
- selectメソッドの基本的な使い方(CSSセレクタによる抽出)
- find、find_allメソッドの基本的な使い方(HTMLタグによる抽出)
- 階層化されたサイトをクローリングする方法(複数ページを移動・遷移しテキストを取得)
- HTMLの階層を移動してタグを指定する方法
- find_allメソッドの使い方の詳細解説
- findメソッドの使い方の詳細解説
- selectメソッドの使い方の詳細解説
- Seleniumと連携し画像ファイルをダウンロード・保存する方法
PythonのWEBスクレイピング用ライブラリとその違い(Selenium、BeautifulSoup、Requests)
WEBスクレイピングの手順
まずはスクレイピングの手順を確認した上で、その中で各ライブラリの役割の違いについて見ていきましょう。
スクレイピングは、次の3ステップで行われます。
1つ目はWEBサイトのHTMLなどのデータ取得です。ただし、HTMLには必要な文章のデータだけでなく、タグなどのデータも混じっているので、必要なものだけを抽出する作業が必要になります。
そこで2つ目のデータの抽出が欠かせません。ここでは、複雑な構造のHTMLデータを解析し、必要な情報だけを抽出します。
そして最後に抽出した情報をデータベースやファイルなどに保存します。
WEBスクレイピングに利用する各ライブラリの役割
Pythonのスクレイピングによく使われるライブラリとしては、Requests、Beautiful Soup、Seleniumがあります。
先ほどのWEBスクレイピングの3ステップの中で、それぞれのライブラリがどこで使われるのかをまとめると次のようになります。
Requestsは1つ目のHTMLデータの取得によく用いられます。PythonではRequestsを利用して、簡単にWEBサイトからデータを自動的に取得することができます。
その後、取得したデータからBeautiful Soupなどのライブラリを用いて必要な情報のみを抽出します。
そしてSeleniumは、JavaScriptが使われているサイトからのデータの取得や、サイトへのログインなどに使います。
Seleniumは、データ取得だけでなく、データの抽出も行うことができますが、ブラウザを操作してデータを取得しますので、動作が遅いことが難点です。
従って、できるだけRequestsやBeautiful Soupを使い、Seleniumは必要最低限の箇所で使うことをお勧めします。この記事ではBeautiful Soupの基本的な使い方を解説していきます。
またBeautifulSoup、Selenium、Requestsについて、もし動画教材で体系的に学ばれたい方は、以下の割引クーポンをご利用いただければと思います。クリックすると自動的に適用されます。期間限定になりますのでお早めに。
>> 「Pythonによるビジネスに役立つWebスクレイピング(BeautifulSoup、Selenium、Requests)(Udemyへのリンク)
発売数10,000本突破記念で、期間限定で88%オフの大セール中!!!
BeautifulSoup4と関連ライブラリのインストール
Beautiful Soupは、標準ではインストールされていませんので、pipやcondaを利用して別途インストールする必要があります。最新のバージョンはBeautiful Soup4になります。
pipを利用してインストールする場合は、以下のコマンドを入力してください。
pipの詳しい説明は「Pythonでの外部ライブラリの追加インストール方法」を参照ください。
またcondaを利用してインストールする場合は、次のコマンドを入力してください。
condaの詳しい説明は「Anacondaでの外部ライブラリの追加インストール方法」を参照ください。
またBeautiful Soup自体はHTMLファイルやXMLファイルを解析するライブラリで、ファイルデータのダウンロードは行いません。
Beautiful Soupでファイルを解析するには、ファイルデータをダウンロードする必要がありますので、必要なライブラリrequestsもインストールします。requestsの詳しい説明は、「図解!PythonのRequestsを徹底解説!」を参照ください。
requests をpipでインストールする場合は、次のコマンドを入力してください。
またcondaでインストールする場合は、次のコマンドを入力してください。
これでインストールは終わりました。次に、これらのライブラリを利用する前にはインポートしておく必要があります。
1 2 | import requests from bs4 import BeautifulSoup |
以上で、Beautiful Soupを使うための準備は終わりです。
BeautifulSoupの前に必要なRequestsを使ったデータの取得方法
これからBeautiful Soupの基本となる使い方を紹介していきます。ここはでは、読売新聞オンライン(https://www.yomiuri.co.jp/) から記事を取得してみます。
まず今回は、メインページのトップニュースのタイトル(赤線で囲った箇所)とそのURLを取得したいと思います。
まずはrequestsを利用して、WEBサイトの情報をダウンロードします。requestsの詳しい説明は、「図解!PythonのRequestsを徹底解説!」を参照ください。
変数urlを定義し、確認したいWEBサイトのアドレスを渡します。次に、requests.get()に対してurlを渡しています。request.get()で指定されたwebの情報を取得し、その結果は、変数resに格納します。
1 2 | url = 'https://www.yomiuri.co.jp' res = requests.get(url) |
試しに取得した内容を表示してみましょう。textで内容を確認することができます。
1 | res.text |

WEBサイトの大量の情報が取り込まれています。
発売数10,000本突破記念で、期間限定で88%オフの大セール中!!!
BeautifulSoupの基礎的な使い方
次に、この情報の中からトップニュースのタイトルとURLを取り出してみましょう。そのためには、BeautifulSoup()を用いて、ダウンロードした情報の解析が必要になります。
BeautifulSoup()の記述方法は以下です。
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を利用します。
参考までにパーサーとしてlxmlを使う場合、pipやcondaを利用して別途インストールする必要があります。
pipを利用してインストールする場合は、以下のコマンドを入力してください。
またcondaを利用してライブラリをインストールする場合は、次のコマンドを入力してください。
BeautifulSoup()に先ほど取得したWEBサイトの情報とパーサー"html.parser"を渡してあげます。
1 | soup = BeautifulSoup(res.text, "html.parser") |
これらの情報を用いてBeautiful SoupではHTMLを解析していきますが、必要な箇所を解析するために、該当箇所を指定、検索する方法がいくつかあります。
- 1つ目は、selectメソッドにより、CSSセレクタで該当する箇所を指定する方法です。
- 2つ目は、find、find_allメソッドにより、HTMLタグの該当する箇所を検索する方法です。
- 3つ目は、HTMLの階層を移動して、HTMLタグの該当する箇所を検索する方法です。
これらの方法を順番に解説していきます。ここではまず、1つ目のselectメソッドによりCSSセレクタで指定する方法を確認していきましょう。
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セレクタになります。
これを用いて、Beautiful Soupで解析を進めていきますが、1つサポートされていないCSSセレクタ、nth-childがあります(該当箇所の背景色を変えています)。nth-childをnth-of-typeに変更する必要があります。
変更後
このようにして取得したCSSセレクタをsoup.select()に渡します。戻り値は、変数elemsに格納します。
1 | 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の最初の要素を表示してみます。
1 | elems[0] |
指定したトップニュースのタイトルやリンクが表示されました。但し、HTMLのタグが混在しており、見やすい状態とは言えません。
次にcontentsを利用して内容を表示してみます。contenstの詳細はこちらを参照ください。
1 | elems[0].contents[0] |
トップニュースのタイトルだけを取り出すことができました。
今度はリンクのURLだけを取得したいと思います。リンクが含まれているaタグのhref属性の内容だけを抽出するattrs['href']を利用します。タグの属性値の確認方法はこちらを参照ください。
1 | elems[0].attrs['href'] |
このようにselectメソッドでCSSセレクタを利用して、指定したトップニュースのタイトルやリンクを取得することができました。
selectメソッドの使い方の詳細については、この記事の後の章で解説いたします。
>> select()の詳細解説へのリンク
find、find_allメソッドの基本的な使い方(HTMLタグによる抽出)
前回はCSSセレクタを利用して情報を抽出しましたが、次は、HTMLタグで該当する箇所を検索する方法を試してみましょう。
ここはでは、yahoo(https://www.yahoo.co.jp/) から記事を取得してみます。今回は、メインページのトップニュースから、タイトル(赤線で囲った箇所)とそのURLの組み合わせの一覧を取得したいと思います。
前回同様、requestsを利用して、WEBサイトの情報をダウンロードします。変数urlを定義し、確認したいWEBサイトのアドレスを渡します。次に、requests.get()に対してurlを渡しています。request.get()で指定されたwebの情報を取得し、その結果は、変数resに格納します。
1 2 | url = 'https://www.yahoo.co.jp/' res = requests.get(url) |
BeautifulSoup()に先ほど取得したWEBサイトの情報とパーサー"html.parser"を渡してあげます。
1 | soup = BeautifulSoup(res.text, "html.parser") |
これらの情報を用いてBeautiful SoupではHTMLを解析していきますが、該当箇所を指定、検索する方法の中で、今回は、HTMLタグで該当する箇所を検索する方法を利用します。
Beautiful Soupでは、HTMLタグで該当する箇所を検索するメソッドには次のようなものがあります。
メソッド | 引数 | 説明 |
find() | 検索するHTMLタグ | 引数に一致する 最初の1つの 要素を取得します。 |
find_all() | 検索するHTMLタグ | 引数に一致する 全ての 要素を取得します。 |
各メソッドの使い方の詳細については、この記事の後の章で解説いたします。
>> find_all()の詳細解説へのリンク
>> find()の詳細解説へのリンク
ここではまず使い方の概要を理解しましょう。
最初に該当する箇所のHTMLタグを確認します。ブラウザでyahooのページを開きます。(ここでは、Google Chromeの例を載せていますが、他のブラウザでも確認できます。)
メインページのトップニュースのタイトルにマウスのカーソルを当て、右クリックします。するとメニューが表示されますので、その中から「検証」を選択します。
すると、右側にウィンドウが現れ、HTMLが表示されます。先ほどのトップページのニュースは、htmlのタグで<a href=”url”>…</a>のように記載されているようです。
タグ<a>は、リンクの開始点と終了点を指定するタグです。リンクの開始点ではhref属性でリンク先を指定しています。
ここで先ほどのメソッドを試してみましょう。まずはfind()に引数”a”を渡すと、
1 2 | elems = soup.find("a") elems |
タグ<a>が含まれる内容が表示されましたが、欲しい情報ではないようです。find()では、引数で渡されたタグで検索してヒットした、最初の1つの 要素を取得しますので、その内容が表示されているようです。
次に、find_all()に引数"a"を渡して、検索してみます。
1 2 | elems = soup.find_all("a") elems |

今度は、タグ<a>が含まれる全ての要素が表示されました。ここから必要な情報だけに絞り込む必要があるようです。
どのようにして絞り込めば良いのでしょうか?先ほど表示された内容をよく見てみると、トップニュースに該当する箇所は全て、URLに"news.yahoo.co.jp/pickup"が含まれているようです。これが利用できそうです。
ということで、URLに”news.yahoo.co.jp/pickup”が含まれているという条件でさらに絞り込んでいきましょう。
ここで文字列のパターンで検索できるモジュールreをインポートします。モジュールreの詳しい説明は、「図解!Python 正規表現の徹底解説!」を参照ください。
1 | import re |
ライブラリreのcompile()を利用して、href=re.compile("news.yahoo.co.jp/pickup") をfind_all()の引数として渡します。
ここでは、href属性の中で"news.yahoo.co.jp/pickup"が含まれているもののみ全て抽出しています。そして抽出した結果を表示すると、
1 2 | elems = soup.find_all(href=re.compile("news.yahoo.co.jp/pickup")) elems |

表示したいトップニュースの箇所に絞り込んで情報を表示することができました。
後は、ここからURLとタイトルを抽出して一覧表示するだけです。ここからは前回学習した内容を活かすことができそうです。
まずは1つ目のニュースのタイトルを表示してみます。contentsを使えばよかったですね。
1 | elems[0].contents[0] |
トップニュースの1つ目のタイトルだけを取り出すことができました。
今度はリンクのURLだけを取得したいと思います。リンクが含まれているタグhrefの内容だけを抽出するattrs['href']を利用します。
1 | elems[0].attrs['href'] |
同様に、2つ目のニュースも取得してみましょう。リストelemsの2つ目の要素を表示するよう、elems[0]からelems[1]に変更します。
1 | elems[1].contents[0] |
2つ目のニュースのURLも同様に、elems[0]からelems[1]に変更すると表示されました。
1 | elems[1].attrs['href'] |
このようにしてリストelemsに格納されている全ての要素のcontensとhref属性を取得すれば、タイトルとURLの一覧を表示することができます。全ての要素の表示はfor文を使って次のように書きます。
1 2 3 | for elem in elems: print(elem.contents[0]) print(elem.attrs['href']) |

このようにして、yahooのトップページからニュースのタイトルとURLの一覧を取得することができました。
階層化されたサイトをクローリングする方法(複数ページを移動・遷移しテキストを取得)
前回はyahoo(https://www.yahoo.co.jp/) のメインページのトップニュースから、タイトル(赤線で囲った箇所)とそのURLの組み合わせの一覧を取得しました。
今回はそのリンクをたどって、それぞれのニュースの詳細な情報も取得してみましょう。
Yahooのサイトは階層化されていて、最終的にニュースの情報を取得するには複数のページを移動していく必要があります。
まずは主要ニュースの一覧が表示されていて、そのリンクをクリックすると、Pickupニュース用の要約が表示されたページに遷移します。
そして、「…続きを読む」のリンクを押すと、ニュースの詳細が書かれたページに遷移します。
この一連のページ遷移を、一覧に表示されている主要ニュースの数だけ繰り返すことにより、全てのニュースの詳細な情報を取得することができます。
それでは実際にコーディングを進めていきます。
前回、記述したコードは次のものでした。今回は、この続きから始めます。
1 2 3 4 5 6 7 8 9 10 11 12 | import requests from bs4 import BeautifulSoup import re url = "https://www.yahoo.co.jp/" res = requests.get(url) soup = BeautifulSoup(res.text, "html.parser") elems = soup.find_all(href=re.compile("news.yahoo.co.jp/pickup")) for elem in elems: print(elem.contents[0]) print(elem.attrs['href']) |
最初に主要ニュースの一覧からPickupページへのリンクを取得します。
またこのリンクは、後から1つずつ取り出して処理しやすいよう、リスト型にして変数に入れておきたいと思います。
ということで、前回記述した一覧からタイトルとリンクを取得・表示したコードを変更します。
print(elem.contents[0])
print(elem.attrs['href'])
リンクを取得するコードを利用して [ ] で括り、リスト内包表記という記述方法で取得したリンクの一覧をリスト型にします。
そして、そのリストの内容を変数pickup_linksに格納します。
格納した内容をprint()で表示してみましょう。
1 2 | pickup_links = [elem.attrs['href'] for elem in elems] print(pickup_links) |
主要ニュースの一覧から取得したPickupページのURLがリストで格納されていることがわかります。
次にそれぞれのURLを元に、Pickupページ、ニュースページへと階層をクローリングして、ニュースページの情報を取得しましょう。
ニュースページからテキスト情報を取得・表示するコードは、次のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #一覧のリンクを順に処理 for pickup_link in pickup_links: #Pickupページへ遷移しページの情報を取得 pickup_res = requests.get(pickup_link) pickup_soup = BeautifulSoup(pickup_res.text, "html.parser") #ニュースページへのリンクを取得 pickup_elem = pickup_soup.find("p", class_="pickupMain_detailLink") news_link = pickup_elem.contents[0].attrs['href'] #ニュースページの情報を取得 news_res = requests.get(news_link) news_soup = BeautifulSoup(news_res.text, "html.parser") #タイトルとURLを表示 print(news_soup.title.text) print(news_link) #ニュースのテキスト情報を取得し表示 detail_text = news_soup.find(class_=re.compile("DetailText")) print(detail_text.text if hasattr(detail_text, "text") else '',end='\n\n\n\n') |
コードを詳しく解説していきます。
先ほどリストに格納したニュースのURLを、for文で1つずつ取り出しながら繰り返し処理を実行していきます。
for pickup_link in pickup_links:
1つのニュースのURLは、変数pickup_linkに格納され、以降の処理を実施します。
変数pickup_linkに格納されたURLを元に、requests.get()でPickupページの情報をダウンロードします。
pickup_res = requests.get(pickup_link)
pickup_soup = BeautifulSoup(pickup_res.text, "html.parser")
そして、BeautifulSoup()を使ってその内容の解析を始めます。
Pickupページからニュースページへ遷移するURLはどのようにして取得すれば良いでしょうか?前回と同様にChromeの検証で確認しましょう。
「…続きを読む」のリンクにマウスのカーソルを当て、右クリックします。するとメニューが表示されますので、その中から「検証」を選択します。
該当箇所のHTMLを確認すると、class属性”pickupMain_detailLink”を持つpタグの配下にaタグがあります。
そして、そのaタグのhref属性にリンクが格納されているようです。
まずはfind()でclass属性”pickupMain_detailLink”を持つpタグを取得します。
pickup_elem = pickup_soup.find("p", class_="pickupMain_detailLink")
news_link = pickup_elem.contents[0].attrs['href']
次にpタグの最初の子要素をcontents[0]で取得し、そのhref属性を変数news_linkに格納します。
この取得したURLを元に、requests.get()でニュースページの情報をダウンロードします。
news_res = requests.get(news_link)
news_soup = BeautifulSoup(news_res.text, "html.parser")
そして、BeautifulSoup()で解析します。
これから取得したニュースページの情報を表示します。
まずはタイトルとURLを表示します。タイトルは通常、titleタグのtext属性に含まれます。
print(news_soup.title.text)
print(news_link)
そしていよいよニュースの内容を表示しますが、ここでもどのようにすれば取得できるでしょうか?ここでもChromeの検証で確認しましょう。
ニュースのテキストの箇所にカーソルを当て、右クリックでメニューを表示します。そして「検証」を選択します。
そして該当箇所のHTMLを確認すると、class属性”ynDetailText yjDirectSLinkTarget”を持つpタグのテキストの中に、ニュースの本文が含まれていることがわかります。
ここではclass属性に”DetailText”を含む要素をあいまい検索しましょう。文字列のパターンで検索できるライブラリreを使います。
ライブラリreのcompile()を利用して、class_=re.compile("DetailText") をfind ()の引数として渡します。ここでは、class属性の中で"DetailText"が含まれているものを抽出しています。
detail_text = news_soup.find(class_=re.compile("DetailText"))
print(detail_text.text if hasattr(detail_text, "text") else '',end='\n\n\n\n')
そして抽出した結果をprint()で表示しています。
その際、text属性がある場合はそのままtextの内容を、無い場合は’’(シングルクォーテーションが2つ)で何も表示しないようにしています。
また最後にはend引数に改行文字\nを4つ渡し、それぞれ取得した主要ニュースのテキストの間隔を空けるようにしています。
実行結果は、次のようになります。

(以下、省略)
1つ目のニュースのタイトル、URL、本文が表示され、そして、2つ目と続いて表示されました。最終的に主要ニュース一覧に表示されていた8つのニュースの本文が表示されます。
このようにして、Yahooの主要ニュースのように、階層化されたサイトのリンクを順にクローリングしながら、最終的に必要なニュースのテキスト情報を表示することができました。
HTMLの階層を移動してタグを指定する方法
Beautiful Soupはスクレイピングにおいて、HTMLの中から特定の情報を指定し取得するのに利用されます。
HTMLは次のようにタグと言う記号で構成されており、開始タグ、終了タグで囲まれたものを要素といいます。
上記の要素はtitleタグに囲まれていますので、titile要素と言います。※この記事でのtitleタグなどXXタグという言い方は、titile要素などXX要素と同じ意味で用いています。
またHTMLは、1つのタグが別のタグで囲われ、というように入れ子の状態で記述されます。これらは階層構造とみなすことができます。
例えば次のHTMLについては、
このような階層構造で表すことができます。
これらの階層構造の中には、同じ要素が含まれます。従って、Beautiful Soupで特定の要素を指定するには、うまく階層をたどる必要があります。
またHTMLのタグの中には、いくつかの属性が含まれることがあります。
これらは属性と属性値からなり、上記のclass属性の属性値は"book"になります。またその横のid="link1"も属性と属性値です。
属性にはid属性のように、HTMLの中で必ず重複しない属性値を持つものと、そうでないものとがあります。
Beautiful Soupでは、これらの属性を取得したり、これらの属性も組合せながら要素を指定したりします。
BeautifulSoupでの基本的なタグの指定方法
ここではまずBeautiful Soupでの基本的なタグの指定方法を説明していきます。
この基本的な書き方を理解した上で、後から説明する階層の前後をたどって要素を指定する方法などの応用的なトピックに進んでいってください。
サンプルコード
以降の章の説明で利用するコードを記載しておきます。HTMLをBeautifulSoup()へ渡すまでのコードになります。これを元に次の章のコードを実行してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from bs4 import BeautifulSoup html = """ <html> <head> <title>清水義孝の著書</title> </head> <body> <p class="title"> <b>清水義孝の最新の著書には、次の本があります。</b> </p> <p class="recent books"> <a class="book" href="https://www.amazon.co.jp/dp/B07TN4D3HG" id="link1"> Python3によるビジネスに役立つデータ分析入門 </a> <a class="book" href="http://www.amazon.co.jp/dp/B07SRLRS4M" id="link2"> よくわかるPython3入門2.NumPy・Matplotlib編 </a> <a class="book" href="http://www.amazon.co.jp/dp/B07T9SZ96B" id="link3"> よくわかるPython3入門4.Pandasでデータ分析編 </a> </p> <p class="end"> <b>そして、これらの本は好評発売中です。</b> </p> </body> </html> """ soup = BeautifulSoup(html,'html.parser') |
上記のHTMLは、実際にブラウザで表示すると次のようになります。
ルート(最上位層)からの指定方法
HTMLのルート(html要素)から指定する場合は、「.」(ドット)を使って記述します。
例えば、html – head – titleとたどってtitle要素を指定する場合、次のように書きます。
1 | print(soup.html.head.title) |
パス(階層)を省略して指定する方法
HTMLのルート(html要素)からではなく、パス(階層)を省略して途中から指定することもできます。
先ほどの例から.html.head を省略してtitleから記述してみましょう。
1 | print(soup.title) |
同様にtitle要素の内容が表示されました。
ここでは、例のHTMLにtitle1つしか含まれませんでしたので、表示された結果は、soup.html.head.titleと指定したのと同じです。
但し、HTMLの中にtitle要素がいくつか存在する場合に省略して記述すると、最初の要素が取得されます。
例えば、.body.pと指定すると、
1 | print(soup.body.p) |
<b>清水義孝の最新の著書には、次の本があります。</b>
</p>
bodyに含まれる3つのp要素の内、最初のものが表示されました。
その他の要素も取得したい場合、find_all()を使って取得するなどの工夫が必要になります。
1 2 | for p in soup.body.find_all("p"): print(p,end="\n\n") |
<b>清水義孝の最新の著書には、次の本があります。</b>
</p>
<p class="recent books">
<a class="book" href="https://www.amazon.co.jp/dp/B07TN4D3HG" id="link1">
Python3によるビジネスに役立つデータ分析入門
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07SRLRS4M" id="link2">
よくわかるPython3入門2.NumPy・Matplotlib編
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07T9SZ96B" id="link3">
よくわかるPython3入門4.Pandasでデータ分析編
</a>
</p>
<p class="end">
<b>そして、これらの本は好評発売中です。</b>
</p>
bodyに含まれる3つのp要素が表示されました。それぞれの要素の間はprint()の引数end="\n\n"(出力後に改行を2つ挿入)の指定により改行しています。
テキストの表示: .string
要素に含まれるテキストを表示したい場合は .stringを使います。ここではtitleのテキストを表示しています。
1 | print(soup.title.string) |
全てのテキストの表示: get_text()
ページに含まれる全てのテキストを表示したい場合は get_text()を使います。
1 | print(soup.get_text()) |
清水義孝の最新の著書には、次の本があります。
Python3によるビジネスに役立つデータ分析入門
よくわかるPython3入門2.NumPy・Matplotlib編
よくわかるPython3入門4.Pandasでデータ分析編
そして、これらの本は好評発売中です。
属性値の表示: [] / get()
要素に含まれる属性の値を表示したい場合は [](スクェアブラケット)を使います。ここではbody配下のp要素に含まれるclass属性の値を表示しています。
1 | print(soup.body.p["class"]) |
属性に複数の値がある場合、リストに複数の値が入ります。
ここではbody配下の2つ目のp要素に含まれるclass属性の値を表示しています。next_siblingについては後ほど解説します。
1 | print(soup.body.p.next_sibling.next_sibling["class"]) |
2つ目のpタグは、<p class="recent books">となっています。class属性に空白を挟んで2つの単語がある場合、2つの属性値があるとみなされます。
また属性値はget()でも取得することができます。
1 | print(soup.body.p.get("class")) |
HTMLを整形して表示: print + prettify
prettify()を使うと1行に1タグのきれいにフォーマットされた形式でHTMLの内容を確認できます。
prettify()は次のように記述します。
1 | print(soup.prettify()) |

親・先祖・兄弟・子・子孫要素の指定方法
今までの説明では、ルートもしくは途中のパスからから階層を降りて目的の要素を指定していました。
例えば、html – head – titleとたどってtitle要素を指定する場合、次のように書きます。
1 | print(soup.html.head.title) |
但し、時にはある要素の親の要素やそのさらに親の要素(先祖要素)、子の要素とその子の要素(子孫要素)、同じ親を持つ子要素同士(兄弟要素)などを指定する必要があります。
これらはBeautiful Soupでは属性を使って指定します。
属性には次のようなものがあります。
属性 | 説明 |
.contents | 子要素(リスト型) |
.children | 子要素(イテレータ型) |
.descendants | 子孫要素 |
.parent | 親要素 |
.parents | 先祖要素 |
.next_sibling | 次の兄弟要素 |
.previous_sibling | 前の兄弟要素 |
.next_siblings | 次の全ての兄弟要素 |
.previous_siblings | 前の全ての兄弟要素 |
ここではこれらの属性の指定方法を詳しく確認していきます。
HTMLの階層構造
親・先祖・兄弟・子・子孫要素の指定方法を確認する前に、兄弟要素や先祖要素などの言葉の定義を確認しましょう。
親・子・兄弟要素
ここでは、自分自身の要素を赤色のp要素とします。そこから1階層上に上がったbody要素(オレンジ色)が親要素になります。
また1つ階層を下に降りたa要素(黄色)が子要素になります。また同じ親要素の子である緑色のp要素は兄弟要素と呼ばれます。
先祖・子孫要素
また同様に自分自身の要素を赤色のp要素とします。そこから1階層上に上がったbody要素とさらに階層を上がったその親要素htmlが先祖要素(オレンジ色)になります。
そして、階層を下に順に下がっていった要素は子孫要素(黄色)と言います。
子要素の取得: .contents / .children
自分自身をbody要素(赤色)とすると、子要素とは黄色の要素になります。
これらの子の要素を取得するには、属性に.contentsを指定します。
1 2 | for child in soup.body.contents: print(child,end="\n\n") |
<b>清水義孝の最新の著書には、次の本があります。</b>
</p>
<p class="recent books">
<a class="book" href="https://www.amazon.co.jp/dp/B07TN4D3HG" id="link1">
Python3によるビジネスに役立つデータ分析入門
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07SRLRS4M" id="link2">
よくわかるPython3入門2.NumPy・Matplotlib編
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07T9SZ96B" id="link3">
よくわかるPython3入門4.Pandasでデータ分析編
</a>
</p>
<p class="end">
<b>そして、これらの本は好評発売中です。</b>
</p>
contents属性はリストで返ってくるので、インデックスを指定して好きな要素にアクセスすることができます。但し、HTMLには空白や改行が含まれますので、注意が必要です。
1 | print(soup.body.contents[0]) |
何も表示されませんでした。インデックス0には空白や改行が入っていたようです。
インデックス1を指定すると、
1 | print(soup.body.contents[1]) |
<b>清水義孝の最新の著書には、次の本があります。</b>
</p>
最初のp要素の内容が表示されました。このようにして、インデックスを指定して、各要素にアクセスすることができます。
また子要素は.childrenでも取得することができます。こちらはイテレータで返ってきますので、各要素に順序どおりにアクセスするのに使います。
1 2 | for child in soup.body.children: print(child, end="\n\n") |
<b>清水義孝の最新の著書には、次の本があります。</b>
</p>
<p class="recent books">
<a class="book" href="https://www.amazon.co.jp/dp/B07TN4D3HG" id="link1">
Python3によるビジネスに役立つデータ分析入門
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07SRLRS4M" id="link2">
よくわかるPython3入門2.NumPy・Matplotlib編
</a>
<a class="book" href="http://www.amazon.co.jp/dp/B07T9SZ96B" id="link3">
よくわかるPython3入門4.Pandasでデータ分析編
</a>
</p>
<p class="end">
<b>そして、これらの本は好評発売中です。</b>
</p>
子孫要素の取得: .descendants
自分自身の要素をhead要素(赤色)とすると、子孫の要素は黄色の要素になります。
子孫要素を取得するには、属性に.descendantsを指定します。
1 2 | for child in soup.head.descendants: print(child,end="\n\n") |
清水義孝の著書
ここではtitile要素とその子要素のテキストが表示されました。
親要素の取得: .parent
今度は自分自身の要素をtitle要素(赤色)とすると、親要素は黄色のhead要素になります。