きっかけ
気象データを取得したいと思い気象庁のサイトにアクセスしたところ、なぜかエラーになりCSVダウンロードができませんでした。
Web上での表示は問題無くできますので、この表データをCSV化できないかを考えました。
すでにやられていたこと
調べてみると、気象データのスクレイピングは様々な方がチャレンジされていました。
なかでも、こちらの記事のソースコードをそのまま実行すれば私の環境でも動きました。
非常に助かりました。
ちなみに、Pythonでは、BeautifulSoupというライブラリを使うのが定石のようです。
このようなコマンドでインストールできます。
pip3 install beautifulsoup4
今回試したこと
前述のブログでは1時間値を取得していましたので、10分値のデータを取得できるようにコードを変更してみました。
prec_no
が都道府県の番号、block_no
が地点の番号を示しているので、実行する時には好きな番号に書き換えてもらえばと思います。
# -*- coding: utf-8 -*-
import os
import datetime
import csv
import urllib.request
from bs4 import BeautifulSoup
def str2float(weather_data):
return weather_data
def scraping(url, date):
# 気象データのページを取得
html = urllib.request.urlopen(url).read()
soup = BeautifulSoup(html)
trs = soup.find("table", { "class" : "data2_s" })
data_list = []
data_list_per_hour = []
# table の中身を取得
for tr in trs.findAll('tr')[3:]: # 変更
tds = tr.findAll('td')
if tds[1].string == None:
break;
data_list.append(date)
data_list.append(tds[0].string)
data_list.append(str2float(tds[1].string))
data_list.append(str2float(tds[2].string))
data_list.append(str2float(tds[3].string))
data_list.append(str2float(tds[4].string))
data_list.append(str2float(tds[5].string))
data_list.append(str2float(tds[6].string))
data_list.append(str2float(tds[7].string))
data_list.append(str2float(tds[8].string))
#data_list.append(str2float(tds[9].string)) # 変更
#data_list.append(str2float(tds[10].string))
#data_list.append(str2float(tds[11].string))
#data_list.append(str2float(tds[12].string))
#data_list.append(str2float(tds[13].string))
data_list_per_hour.append(data_list)
data_list = []
return data_list_per_hour
def create_csv():
# CSV 出力先ディレクトリ
output_dir = r"/Users/username/Downloads"
# 出力ファイル名
output_file = "weather.csv"
# データ取得開始・終了日
start_date = datetime.date(2023, 1, 1)
end_date = datetime.date(2023, 1, 2)
# CSV の列
fields = ["年月日", "時間", "降水量", "気温", "相対湿度",
"平均風速", "平均風向", "最大瞬間風速", "最大瞬間風向", "日照時間"]
with open(os.path.join(output_dir, output_file), 'w') as f:
writer = csv.writer(f, lineterminator='\n')
writer.writerow(fields)
date = start_date
while date != end_date + datetime.timedelta(1):
# 対象url(10分値の場合)
url = "http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php?" \
"prec_no=46&block_no=0388&year=%d&month=%d&day=%d&view="%(date.year, date.month, date.day)
data_per_day = scraping(url, date)
for dpd in data_per_day:
writer.writerow(dpd)
date += datetime.timedelta(1)
if __name__ == '__main__':
create_csv()
補足
10分値のデータは1時間とは取得できる表の列名が異なるため、その部分だけ書き換えています。
元の記事には、str2float()という関数があったのですが、テキスト値も一律に0に変換されてしまうので、取り急ぎ無意味な処理にしています。
もっと簡単にしたり、数値と文字列で適切な処理に変更することもできそうです。