はじめに
こんにちは、らっじです
今回は、Pythonでスクレイピングする方法を解説します
環境
以下の環境で実行してます
- Ubuntu 24.04 LTS x86_64 (Proxmox)
- Python 3.12.3 venv
- beautifulsoup4 4.12.3
- requests 2.32.3
beautifulsoup4とrequestsはpipでインストールしています
スクレイピングとは
WebページはHTMLで書かれていて、それを解析して必要な情報を抜き出すことをスクレイピングといいます
スクレイピングをしまくるとサーバーに負荷がかかったりするので、スクレイピングを禁止しているサイトもあります
スクレイピングの手法は大きく分けて、
- HTTPリクエストを送り、返ってきたレスポンスのHTMLを解析する
- ブラウザをスクリプトで操作して情報を取り出す
という2種類がありますが、今回は1のほうをやります
(2のほうはSeleniumというライブラリでできるので興味があったら調べてみてください)
手順
今回は試しに、Yahoo天気から今日明日の東京の天気を取得してみます
HTTPリクエスト
まずは、解析したいサイトにHTTPリクエストを送り、HTMLを取得します
import requests
url = "https://weather.yahoo.co.jp/weather/jp/13/4410.html" # Yahoo天気のURL
response = requests.get(url)
print(response.text)
これでHTMLが標準出力に表示されるはずです
BeautifulSoup4で解析
次に、取得したHTMLをパーサーに読みこませます
from bs4 import BeautifulSoup4
soup = BeautifulSoup4(response.text, "html.parser")
print(soup.title)
このようにすると、titleタグのみを抜きだせているはずです
では実際に天気の情報を取得してみましょう
まずは、欲しい情報がHTML内のどこにあるかを探します
Chromeを使っている場合は、欲しい要素上で右クリックして「検証」というメニューを押すと、ページのソースが表示されて分かりやすいです
見ていくと、forecastCity
というclassのdivの中にtableがあって、その中をたどっていくと、2つのtdにそれぞれ今日と明日の情報が入っていて~という感じにわかってきます
これをコードに書いていくと最終的に以下のようになります
td = soup.find(class_="forecastCity").find("tr").find_all("td", recursive=False) # td[0]が今日でtd[1]が明日
print(td[0].find(class_="date").text.strip()) # 8月28日(水)
print(td[0].find(class_="pict").text.strip()) # 曇時々晴
print("最高気温: " + td[0].find(class_="high").text.strip()) # 最高気温: 33℃[+1]
print("最低気温: " + td[0].find(class_="low").text.strip()) # 最低気温: 27℃[+1]
print(td[1].find(class_="date").text.strip()) # 8月28日(水)
print(td[1].find(class_="pict").text.strip()) # 曇時々晴
print("最高気温: " + td[1].find(class_="high").text.strip()) # 最高気温: 33℃[+1]
print("最低気温: " + td[1].find(class_="low").text.strip()) # 最低気温: 27℃[+1]
findメソッドやfind_allメソッドで辿っていくことができます
findメソッドは、子要素の中から検索して合致するもののうち1つめを返します
find_allメソッドは、検索結果を全てリスト形式で返します
あとは、.textで中身のテキストを抜き出して、.strip()でいらない空白や改行を削除しています
検索方法はドキュメントを読むのが間違いないと思います
また、CSSを理解している人は、CSSセレクタで探すほうが分かりやすいかもしれません