概要
requests
モジュールまたは urllib.request
モジュールと Beautiful Soup を使用した静的なページのスクレイピング手順について解説します。
スクレイピングの手順
1. HTML の DOM ツリーを把握する
まず、スクレイピングをしたい Web ページをブラウザ (ここでは Chrome を前提とします) で開きます。
開いたら、取得したい情報の要素を右クリックし、「検証」を選択します。すると、ブラウザの右サイドバーに「開発者ツール」が表示されるので、Element
タブを選択します。
HTML は DOM ツリーと呼ばれる木構造になっており、スクレイピングでは DOM ツリーから必要な要素を見つける必要があるため、要素の親子関係がどうなっているかを把握することが重要です。
開発者ツールで確認できる HTML の注意点
Web ページによっては Javascript で動的にコンテンツを生成する作りになっています。 その場合、最初にサーバーから HTML を取得した段階ではそのコンテンツは HTML 上に存在していないことになります。 「開発者ツール」から確認できる HTML 構造は、今現在のものです。サーバーから取得した段階の HTML を確認したい場合は右クリックから「ページのソースを表示」を選択しましょう。
もし、「開発者ツール」上には存在し、「ページのソースを表示」で表示された HTML ソースコード上に存在しなかった場合、その要素は Javascript で後から生成されたものになります。スクレイピングで要素を検索した際に「開発者ツール」上にはあるのに要素が見つからない場合は大抵このパターンなので注意しましょう。
2. HTML を取得する
HTML の取得は先に述べた Javascript で動的に生成されたページかどうかで使用するツールが変わってきます。
- Javascript で動的に生成されたページのスクレイピング: selenium
- 静的なページ:
requests
モジュールまたはurllib.request
モジュール
今回は静的なページをスクレイピングする場合のやり方について解説します。 Javascript で動的に生成されたページのスクレイピングしたい場合は以下の記事を参照してください。
[blogcard url=”https://pystyle.info/scraping-tutorials-for-website-using-javascript”]
題材として、Webスクレイピング用のサンプルサイトとして こちらのページ を利用します。
requests モジュールを使って取得
requests
モジュールは pip install requests
でインストールできます。
Web ページの取得は簡単は、url
を指定して requests.get(url)
を呼び出します。返り値はレスポンスを表す Response
オブジェクトになります。内容は Response.content
で取得できます。
import requests
url = "https://pystyle.info/apps/scraping/"
res = requests.get(url)
if not res.ok:
print(f"ページの取得に失敗しました。status: {res.status_code}, reason: {res.reason}")
else:
html = res.content
Response
オブジェクトの属性やメソッドで以下の情報が取得できます。
属性またはメソッド | 概要 |
---|---|
encoding | 文字コード |
headers | HTTP ヘッダー |
url | ページを取得した URL |
ok | HTTP ステータスコードが200かどうか |
status_code | HTTP ステータスコード |
reason | HTTP ステータスコードの理由 |
iter_content() | コンテンツを1文字ずつ返す |
iter_lines() | コンテンツを1行ずつ返す |
res.json() | コンテンツが JSON の場合に JSON として解析して dict で返す |
raise_for_status() | ページの取得に失敗した場合は例外を送出する |
urllib.request モジュールを使って取得
標準ライブラリの urllib.request
モジュールでも Web ページを取得できます。
単に Web ページを取得するだけであれば、外部ライブラリを使わないこちらのやり方のほうがいいかもしれません。
import urllib.request
url = "https://pystyle.info/apps/scraping/"
req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
html = res.read()
3. 解析する
HTML の解析は BeautifulSoup がおすすめです。BeautifulSoup は pip install beautifulsoup4
でインストールできます。Beautiful Soup の詳しい使い方は以下のページを参照ください。
[blogcard url=”https://pystyle.info/scraping-beautiful-soup-how-to-find-elements”]
[blogcard url=”https://pystyle.info/scraping-beautiful-soup-how-to-refer-elements”]
[blogcard url=”https://pystyle.info/scraping-beautiful-soup-how-to-edit-dom-tree”]
スクレイピング練習用のサンプル には色の情報がテーブルで記載されています。こちらから色の名前と RGB の値を抽出してみます。
Response.content
をBeautifulSoup
オブジェクトに渡すことで、HTML を解析し、DOM ツリーが作成できます。
今回の場合、DOM ツリーは以下のようになっています。
import requests
from bs4 import BeautifulSoup
url = "https://pystyle.info/apps/scraping/"
res = requests.get(url)
soup = BeautifulSoup(res.content)
root (BeautifulSoup) └── html (Tag) ├── head (Tag) │ ├── meta (Tag) │ ├── title 'スクレイピング練習用のサンプル' (Tag) │ └── link (Tag) └── body (Tag) └── main (Tag) ├── h2 '色の一覧' (Tag) └── table (Tag) ├── thead (Tag) │ └── tr (Tag) │ ├── th '名前' (Tag) │ ├── th 'RGB' (Tag) │ └── th '色' (Tag) └── tbody (Tag) ├── tr (Tag) │ ├── td 'Black' (Tag) │ ├── td '(0, 0, 0)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Red' (Tag) │ ├── td '(255, 0, 0)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Green' (Tag) │ ├── td '(0, 255, 0)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Yellow' (Tag) │ ├── td '(255, 255, 0)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Blue' (Tag) │ ├── td '(0, 0, 255)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Magenta' (Tag) │ ├── td '(255, 0, 255)' (Tag) │ └── td '' (Tag) ├── tr (Tag) │ ├── td 'Cyan' (Tag) │ ├── td '(0, 156, 209)' (Tag) │ └── td '' (Tag) └── tr (Tag) ├── td 'White' (Tag) ├── td '(255, 255, 255)' (Tag) └── td '' (Tag)
色の名前と RGB を取得するには以下のようにします。
soup.tbody.find_all("tr")
でtbody
要素以下のtr
要素の一覧を取得するtr_tag.find_all("td")
で各tr
要素以下のtd
要素の一覧を取得するtd
要素の値 (例:Red
、(255, 0, 255)
) はtd_tag.string
で取得する
from pprint import pprint
data = []
for tr_tag in soup.tbody.find_all("tr"):
td_tags = tr_tag.find_all("td")
name = td_tags[0].string
rgb = td_tags[1].string
data.append({"name": name, "rgb": rgb})
pprint(data)
[{'name': 'Black', 'rgb': '(0, 0, 0)'}, {'name': 'Red', 'rgb': '(255, 0, 0)'}, {'name': 'Green', 'rgb': '(0, 255, 0)'}, {'name': 'Yellow', 'rgb': '(255, 255, 0)'}, {'name': 'Blue', 'rgb': '(0, 0, 255)'}, {'name': 'Magenta', 'rgb': '(255, 0, 255)'}, {'name': 'Cyan', 'rgb': '(0, 156, 209)'}, {'name': 'White', 'rgb': '(255, 255, 255)'}]
目的の値が取得できました。
まとめ
スクレイピングの手順をまとめると以下のようになります。
- Web ページをブラウザで開いて、HTML の構造を把握する
- 「Ctrl + Shift + I」キーまたは「F12」を押して「開発者ツール」を開いて、取得したい周辺の HTML の DOM ツリー構造を把握する
- 「Ctrl + U」による「ソースコードの表示」を押して、対象の要素が存在する、つまり、Javascript で動的に作られたコンテンツでないことを確認する。
requests
モジュール、またはurllib.request
モジュールで Web ページの HTML を取得する- Beautiful Soup で解析する
コメント