プログラム関係の備忘録。技術系記事1000記事以上を目指すブログ

pythonでスクレイピング~BeautifulSoup編~

  • 2021年4月15日
  • 2021年4月15日
  • python
  • 278view
  • 0件

はじめに

前回の記事ではurllibを使ったスクレイピング、というよりはWeb上のデータを取得という部分をやりました。
今回はよりスクレイピングっぽい作業をしていきます。

前回との違いは、APIのように予め用意されたものを取得するのではなく、Webページ上の好きな部分を取得するという方法になります。

BeautifulSoup(なんかおいしそう)というライブラリを使っていきます。

BeautifulSoupのインストール

他のライブラリと同様pipでインストール。

pip install beautifulsoup4

BeautifulSoupの使い方

スクレイピングはWeb上のデータの構造を辿っていったり指定したりして求めるデータを取ってくるという形になるのですが、探す方法はいくつか方法があります。

1.素直にWebサイトの構成を上から辿っていく。
2.htmlのID属性を指定して取得する
3.CSSのセレクターを指定して取得する

Webサイトの構成をみてどの方法が簡潔か考慮する必要がありそうです。

以下ではWeb上のhtmlの構成を文字列で置き換えて、それぞれの方法を使った取得方法をメモしていきます。

1.単純な使い方

from bs4 import BeautifulSoup
import sys
import urllib.request as request
import urllib.parse as parse


html = """
<html>
    <body>
        <h1>大見出し</h1>
        <h2>中見出し</h2>
        <p>段落</p>
    </body>
</html>
"""

soup = BeautifulSoup(html, 'html.parser')

text1 = soup.html.body.h1.string
text2 = soup.html.body.h2.string
text3 = soup.html.body.p.string

print(text1,text2,text3)

結果

PS F:\python_prd> python download.py
大見出し 中見出し 段落

解説

# ライブラリ読み込み
from bs4 import BeautifulSoup

# HTMLのモック
html = """
<html>
    <body>
        <h1>大見出し</h1>
        <h2>中見出し</h2>
        <p>段落</p>
    </body>
</html>
"""

# BeautifulSoupで解析
soup = BeautifulSoup(html, 'html.parser')

# 各要素の値を取得
text1 = soup.html.body.h1.string
text2 = soup.html.body.h2.string
text3 = soup.html.body.p.string

print(text1,text2,text3)

上記では要素の文字列を取得していますが、例えば以下のようにすると要素ごと取得が可能です。

soup.html.body.h1
soup.html.body.h2
soup.html.body.p

2-1.find()メソッドでid属性を指定

from bs4 import BeautifulSoup

html = """
<html>
    <body>
        <h1 id="target">大見出し</h1>
        <h2>中見出し</h2>
        <p>段落</p>
    </body>
</html>
"""

soup = BeautifulSoup(html, 'html.parser')
text1 = soup.find(id="target").string

print(text1)

結果

PS F:\python_prd> python download.py
大見出し

解説

# idの属性を指定し、文字列を取得している
text1 = soup.find(id="target").string

2-2.find_all()メソッドで複数要素を取得

from bs4 import BeautifulSoup

html = """
<html>
    <body>
        <h1 id="target">大見出し</h1>
        <h2>中見出し</h2>
        <p>段落</p>
        <p>段落</p>
        <p>段落</p>
    </body>
</html>
"""

soup = BeautifulSoup(html, 'html.parser')
textList = soup.find_all("p")

for text in textList:
    print(text.string)

結果

PS F:\python_prd> python download.py
段落
段落
段落

解説

soup = BeautifulSoup(html, 'html.parser')
# find_allで全て取得
textList = soup.find_all("p")

# ループで一件ずつプリント
for text in textList:
    print(text.string)

3-1.select_one()メソッドでCSSセレクターから取得

from bs4 import BeautifulSoup

html = """
<html>
    <body>
        <div class="container">
            <h1>大見出し</h1>
            <h2>中見出し</h2>
            <div class="list">
                <p>段落</p>
                <p>段落</p>
                <p>段落</p>
            </div>
        </div>
    </body>
</html>
"""

soup = BeautifulSoup(html, 'html.parser')
h1 = soup.select_one("div.container>h1")

print(h1.string)

結果

PS F:\python_prd> python download.py
大見出し

解説

# セレクターを指定
h1 = soup.select_one("div.container>h1")

3-2.select()メソッドでCSSセレクターから取得

from bs4 import BeautifulSoup

html = """
<html>
    <body>
        <div class="container">
            <h1>大見出し</h1>
            <h2>中見出し</h2>
            <div class="list">
                <p>段落</p>
                <p>段落</p>
                <p>段落</p>
            </div>
        </div>
    </body>
</html>
"""

soup = BeautifulSoup(html, 'html.parser')
# セレクターを指定
ps = soup.select("div.container > div.list > p")
for p in ps:
    print(p.string)

結果

PS F:\python_prd> python download.py
段落
段落
段落

実践編

最後に、実際に本ウェブサイトから最新記事の一覧を取得するという処理を作っていきます。
前回の記事で使ったurllibと、今回のBeautifulSoupを使います。

from bs4 import BeautifulSoup
import urllib.request as req

url = "https://weblion303.net/"
res = req.urlopen(url)
soup = BeautifulSoup(res, 'html.parser')

out = soup.select(".heading-secondary > a")

for title in out:
    print(title.string)

結果

PS F:\python_prd> python download.py
pythonでスクレイピング~urllib編~
python:djangoとbootsrap5
初めてのpython
wordpress案件で捗る進め方(リリース関係)
【SwiftUI】外部ブラウザでURLを開きたいときはLinkが使える
【SwiftUI】NavigationViewからフルスクリーン画面を表示する方法
【react-native】シュミレータでAPIアクセスを行う際にnetwork error
rspec最低限の定義
[技術編]年末年始の4日間でサブスク管理のSaaSを開発しました
年末年始の4日間でサブスク管理がサクッとできるSaaSをサクッと作りました
PlantUMLでgraphvizが読み込めなくなった
PluntUMLでシーケンス図とアクティビティ図以外の描画に必要なGraphvizのインストール方法
React/ExpressのアプリをVPSにデプロイするときにやること(apache2編)
【SfiftUI】スタックレイアウトの使い方
【SwiftUI】Imageビューの便利なモデファイア一覧
【SwiftUI】Textビューの便利なモデファイア一覧

解説

url = "https://weblion303.net/"
res = req.urlopen(url)
soup = BeautifulSoup(res, 'html.parser')

# heading-secondaryというクラスがタイトルの共通クラスだったためそれを使用
out = soup.select(".heading-secondary > a")

最後に

今回は少しスクレイピングっぽいところまできました。
ここまででもやりかたによってはいろいろと使えそうですよね!
例えば為替のチャートやFXのチャートなんかを定期的に読み取ったり。

わくわくが止まりません!ってことで今回はここまでです。
ありがとうございました。

おさらい

・soup.html.body.div… のようにピンポイントで指定ができる

・soup.find(id=”***”) で属性から指定ができる

・soup.find_all(***) で複数要素から指定ができる

・soup.select_one(***) でセレクターから指定ができる

・soup.select(***) で複数セレクターから指定ができる