Python
HTML
オープンデータ
beautifulsoup4
気象庁

気象庁の風データをダウンロード

More than 1 year has passed since last update.

気象庁の過去の気象データをダウンロードする.

今回は風.PythonのBeautifulsoupを使ってHTMLをパース.


スクリプト

まずモジュールの準備.


準備

import requests

import bs4
import pandas as pd
import datetime
import time
import numpy as np
from numpy import NaN

次は変換ヘルパー.文字列が数字だったらfloatに変換.///は観測データなしという記号.


ヘルパー

def convert(item_str):

if not item_str:
return ''
if item_str.replace('.','').replace('-','').isdigit():
return float(item_str)
if item_str == '///':
return NaN
return item_str

それでは本体.urlには県番号と場所番号を入れておく.それを探すには

http://www.data.jma.go.jp/obd/stats/etrn/

から順に場所を選択していけばよい.最終的なURLをみてそれをコピーする.

日付はURL指定,時刻はhh:mm形式でやってくるので,JSTに変換するためにdatetime+timedeltaで変換.


本体

columns = ('JST', 'time', '降水量', '気温', '平均風速', '平均風向', '最大瞬間風速', '最大瞬間風速時風向', '日照時間')

all_df = []

for year in range(2015, 2017): # 2015 ... 2016
for month in range(1, 13): # 1 ... 12
for day in range(1, 32): # 1 ... 31

try:
this_day = datetime.datetime(year, month, day)
except ValueError:
continue # incorrect date; e.g., 2007/2/31 etc.
print(this_day)

url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php? prec_no=44&block_no=47662&year=' + str(year) + '&month=' + str(month) + '&day=' + str(day) + '&view='
print(url)
time.sleep(1) # wait for 1 sec
res = requests.get(url)

try:
res.raise_for_status() # check for error
except Exception as e:
print('Error: {}'.format(e))
continue # go to next if error

res.encoding = 'utf-8'
soup = bs4.BeautifulSoup(res.text, "lxml")
tbl = soup.select("#tablefix1 td") # find the table
n_rows = len(tbl) // 8

for r in range(n_rows):
i = 8 * r

# JST
hh, mm = tbl[i + 0].getText().split(":") # '00:10' --> '00', '10'
row_timedelta = datetime.timedelta(hours=int(hh), minutes=int(mm))

row_time = this_day + row_timedelta # for converting "24:00" to "00:00" of the next day
row = [row_time]

# other data
row.extend([convert(tbl[i + j].getText()) for j in range(8)])

row_df = pd.DataFrame(columns=columns)
row_df.loc[0] = row
all_df.append(row_df)

df = pd.concat(all_df, ignore_index=True)
df.to_excel('wind_data.xlsx')