Navigation

Related Articles

Back to Latest Articles

気象庁の天気予報をBeautifulSoup4でスクレイピング


press
気象庁の天気予報をBeautifulSoup4でスクレイピング

気象庁の天気予報をBeautifulSoup4でスクレイピングします。サンプルとして群馬県の週間天気予報(場所、日付、曜日、最高気温、最低気温)を取得します。

コードはGitHubリポジトリにあげています。

週間天気予報のスクレイピング

各要素を取得

週間天気予報の情報以下のテーブル内にあります。

取得するテーブルのソース

日付と曜日は、1個目の<tr>内にあるので、find_all("tr")[0]として1個目の<tr>を取得し、find_all("th")で全ての<th>を取得しています。
days = soup.find("table", {"id": "infotablefont"}).find_all("tr")[0].find_all("th")

取得する日付のソース

citynameという名前のclassは一箇所でしか使われていないので、city = soup.find("th", {"class": "cityname"}).textで場所を取得します。.textを指定することで不要なタグを除いたテキストのみを取得します。

最高気温は、5個目の<tr>内にあるので、find_all("tr")[4]として5個目の<tr>を取得し、find_all("td")で全ての<td>を取得しています。
max_temp = soup.find("table", {"id": "infotablefont"}).find_all("tr")[4].find_all("td")

取得する最高気温のソース

最低気温は、6個目の<tr>内にあるので、find_all("tr")[5]として6個目の<tr>を取得し、find_all("td")で全ての<td>を取得しています。
min_temp = soup.find("table", {"id": "infotablefont"}).find_all("tr")[5].find_all("td")

取得する最低気温のソース

取得した要素の整形

日付・曜日を取得します。
はじめに空のリストを生成して、取得した情報から一件づつ日付・曜日をアペンドします。
day = day.textでテキスト情報のみを取得します。
ここで取得した日付と曜日は「11木」の様に日付と曜日が続いてしまうので、weeklist.append(day[-1])として最後の1文字の曜日のみを取得します。
日付部分を取得するには、daylist.append(day[:-1])として最後の1文字を除いて日付を取得します。
取得した情報には最初に「日付」という文字が入ってしまっているので、if '日付' not in day:として日付と曜日のみを取得しています。

daylist = []
weeklist = []
for day in days:
    day = day.text

    if '日付' not in day:
        weeklist.append(day[-1])
        daylist.append(day[:-1])

最高気温と最低気温を取得します。
はじめに空のリストを生成して、取得した情報から一件づつ気温をアペンドします。
maxtemp = maxtemp.textmintemp = mintemp.textの部分で気温のテキストを取得します。
maxtemp、mintemp共に.replace('\n', '').replace('\t', '').replace('(', '{').replace(')', '}')として、不要なスペースの削除や文字列の変換を行います。ここで取得した情報は「17(15~19)」の様に複数の値が含まれているので、()内の情報を削除するために()を{}に変換しています。
maxtemp = re.sub('{.*?}', '', maxtemp)mintemp = re.sub('{.*?}', '', mintemp)で{}内の情報を削除しています。
時々、取得した気温の部分が「/」になっている場合があるので、if '/' in maxtemp:として値が「/」だったらNoneに置き換えています。
最後に整形した情報をint()で数値に変換してアペンドします。

# 最高気温

maxtemplist = []
for maxtemp in max_temp:
    maxtemp = maxtemp.text

    if '最高' not in maxtemp:
        maxtemp = maxtemp.replace('\n', '').replace('\t', '').replace('(', '{').replace(')', '}')
        maxtemp = re.sub('{.*?}', '', maxtemp)

        if '/' in maxtemp:
            maxtemp = None
        else:
            maxtemp = int(maxtemp)

        maxtemplist.append(maxtemp)
# 最低気温

mintemplist = []
for mintemp in min_temp:
    mintemp = mintemp.text

    if '最低' not in mintemp:
        mintemp = mintemp.replace('\n', '').replace('\t', '').replace('(', '{').replace(')', '}')
        mintemp = re.sub('{.*?}', '', mintemp)

        if '/' in mintemp:
            mintemp = None
        else:
            mintemp = int(mintemp)

        mintemplist.append(mintemp)

最終的なコード

# scraping_weather.py

import re
import urllib.request

from bs4 import BeautifulSoup

url = urllib.request.urlopen('https://www.jma.go.jp/jp/week/315.html')
soup = BeautifulSoup(url, 'lxml')

city = soup.find("th", {"class": "cityname"}).text
days = soup.find("table", {"id": "infotablefont"}).find_all("tr")[0].find_all("th")
max_temp = soup.find("table", {"id": "infotablefont"}).find_all("tr")[4].find_all("td")
min_temp = soup.find("table", {"id": "infotablefont"}).find_all("tr")[5].find_all("td")

weather = []

daylist = []
weeklist = []
for day in days:
    day = day.text

    if '日付' not in day:
        weeklist.append(day[-1])
        daylist.append(day[:-1])

maxtemplist = []
for maxtemp in max_temp:
    maxtemp = maxtemp.text

    if '最高' not in maxtemp:
        maxtemp = maxtemp.replace('\n', '').replace('\t', '').replace('(', '{').replace(')', '}')
        maxtemp = re.sub('{.*?}', '', maxtemp)

        if '/' in maxtemp:
            maxtemp = None
        else:
            maxtemp = int(maxtemp)

        maxtemplist.append(maxtemp)

mintemplist = []
for mintemp in min_temp:
    mintemp = mintemp.text

    if '最低' not in mintemp:
        mintemp = mintemp.replace('\n', '').replace('\t', '').replace('(', '{').replace(')', '}')
        mintemp = re.sub('{.*?}', '', mintemp)

        if '/' in mintemp:
            mintemp = None
        else:
            mintemp = int(mintemp)

        mintemplist.append(mintemp)

weather.append(city)
weather.append(weeklist)
weather.append(daylist)
weather.append(maxtemplist)
weather.append(mintemplist)

print(weather)

出力結果

['前橋', ['木', '金', '土', '日', '月', '火', '水'], ['11', '12', '13', '14', '15', '16', '17'], [24, 24, 31, 29, 26, 29, 27], [18, 17, 21, 21, 20, 22, 21]]

当ブログは群馬県でPython / Djangoを中心にウェブアプリケーションを開発している株式会社ファントムが運営しています。

株式会社ファントムへのお問い合わせ




    Show Comments (2)

    Comments

    • Pythonistaを使って最高気温と最低気温をグラフ化 – Fantom blog

      […] 気象庁の天気予報をBeautifulSoup4でスクレイピング […]

      • Article Author
      • 返信
    • def文を用いて共通の処理を関数化する – Fantom blog

      […] 気象庁の天気予報をBeautifulSoup4でスクレイピング […]

      • Article Author
      • 返信

    Related Articles

    Python

    多次元配列から最大値、最小値を取得

    多次元配列から最大値、最小値を取得 Pythonで複数の配列からなる多次元配列から最大値、最小値を取得する方法です。一次元配列も同じやり方で最大値、最小値を取得可能です。 モジュールのインストール ソースコード arr1 […]

    Posted on by press
    Python

    名前に現在時刻を入れたファイルが連番かどうか判定(前半)

    名前に現在時刻を入れたファイルが連番かどうか判定(前半) なにかアクションがあった際に生成されるファイル名に現在時刻が入ったファイルが、連番になっているかどうかを判別して連番になっていたらまとめてリスト化する方法です。手 […]

    Posted on by press