※スクレイピングする際には各所の利用規約に従うようにしてください。
※本記事を参考に実行して生じた不利益等は責任を負えませんのでご容赦ください。
#概要
Google Colaboratoryを利用したWebスクレイピングでAMeDASの10分値を半自動的にダウンロードします。
#はじめに
気象データとして気象庁が公開しているAMeDASの10分値を使用したい場合、
ダウンロードオプションが用意されていないため、何らかの方法で自ら取得する必要があります。
既にPythonを用いたスクレイピングでAMeDASの10分値等をダウンロードする方法が多く公開されていますが、
何より面倒なのは「環境構築」です(筆者の個人的意見です)。
ライブラリのインストールやパスの設定など、できれば省きたいものです。
例えばGoogle Colaboratoryを使用すれば、webブラウザ上で直ぐにPython環境が利用できます。
但し、Google colaboratoryではwebブラウザ上でPython等を記述・実行する環境構築のために、
Jupyterを用いており、この関係でコマンドの記述方法等を多少変更する必要があります。
※厳密にはJupyterのバックエンドであるIpythonの仕様に合わせるため。
そこでこの記事では、Google Colaboratoryに対応したPythonスクレイピングでAMeDASの10分値を取得する方法を紹介します。
#必要なもの
・Googleアカウント
#Google Colaboratoryの準備
Google ColaboratoryはWeb上で簡単にPythonを使用できる無料ツールです。
Google Colaboratoryを利用する環境の用意については、別記事に詳細を記載していますので、
ここでは簡単に説明します。
ブラウザからGoogle Driveを開き、左上の新規
からその他
、アプリの追加
へと進みます。
アプリ一覧の中にColaboratory
があるので、これをインストールします。
インストール後はGoogle Driveの新規
からその他
へと進むことで、
Colaboratory
を利用できるようになります。
##Google Colaboratoryの使い方(今回必要な分だけ)
上記手順で進めるとGoogle Colaboratoryの編集画面が立ち上がります。
(説明が下手ですが)黒丸に灰色の三角形内包されているものが実行ボタンです。
その右側の灰色の部分がコードを入力できるエリアです。ここに諸々を書き込みます。
プログラムの実行には先の実行のボタンを押しても良し。
Ctrl+Enter
でも良し。
標準出力/エラー出力先はコード入力エリアの下方にあります。
また、画面左側の4つのアイコンが順に[目次][検索と置換][コードスニペット][ファイル]ですので、
ディレクトリ構造等を確認したい場合には、[ファイル]のアイコンをクリックすればクイックビュー可能です。
※注意
Google ColaboratoryはGoogle Driveから入りましたが、
ここでのファイル
はDrive上とは別です。(上で確認できるディレクトリ構造にはDriveが表示されません、初期状態では。)
ColaboratoryからDriveにアクセスするためには、Driveをマウントする必要があります。
Driveのマウント方法について詳しく知りたい方は別記事を参照ください。
(今回紹介するプログラムにも内包しています。)
#ソースコードの概要
今回作成する最終的なソースコードは最後に記載しています。
以下では順に各セクションの説明をします。
##ライブラリのインポート等
Google Colaboratoryでは主要なpythonライブラリをローカル環境にインストールすることなく使用できます。
また、Google Driveをマウントすることで出力先としてgoogle driveを指定できるため、今回は出力先をGoogle Drive内としています。
※Colaboratory(先に紹介したファイル
)内に出力することもできます。デフォルトでは/contents
がカレントディレクトリになっています。
### Import libraries ###
from google.colab import drive
from datetime import datetime
import numpy as np
import pandas as pd
import time
import os
drive.mount('/content/drive')
##出力設定
取得したデータの出力先を指定します。
今回はMyDrive(日本語表記ではマイドライブ)
内にdataというディレクトリを用意して、
さらにその下にpointというディレクトリを作成した上で、ここに出力しようと思います。
(取得ファイルfは、マイドライブ/data/point/*
として保存される。)
まずは出力先のディレクトリodir
を用意します。
odir = `data/point`
次にodir
を実際にMyDrive
配下に作成します。
デフォルトではColaboratory:/contents
にいるため、
(Driveをマウントした状態で)MyDrive
に移動する必要があります。
また、既に同じ名前のディレクトリがあった場合には、そのディレクトリをそのまま使用するようにしています。
## prepare the folder
%cd '/content/drive/MyDrive'
cdir = os.getcwd()
ddir = str(cdir) + '/' + odir
print(ddir)
if not os.path.exists(ddir): os.makedirs(ddir)
また、今回使用するpandasライブラリの出力設定も少し。
(10分値×24時間=144行なので、余裕をもって150。)
pd.set_option('display.max_rows',150)
##スクレイピングの準備
今回はAMeDASの10分値を対象とするので、そのURLについて調べます。
http://www.data.jma.go.jp/obd/stats/etrn/index.php
上記URLから任意の都府県・地方、地点、年月日を指定し、10分ごとの値を表示
へと進むと、以下のURLに移動します。
http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php?prec_no=44&block_no=1002&year=2020&month=1&day=1&view=
(ここでは東京都、練馬、2021年1月1日を指定)
10min_
の後ろが観測区分情報で、a1
がアメダス、s1
が気象台・測候所等を表します(練馬はアメダス区分)。
prec_no
が都府県・地方情報で、2桁の数字で表されます。(練馬であれば「東京」の44)
block_no
が地点情報で、4~5桁の数字で表されます。(練馬であれば1002)
※1000未満の場合は0埋めが必要。(例:0366, 八王子)
year=
、month=
、day=
はそれぞれ年月日情報です。
つまり、以上の4情報(type, prec, block, date)があれば、URLを作成することが出来ます。
ここでは、一回の実行で複数地点を順に取り込めるようにするために、
これら4情報をそれぞれ配列として設定します。
(参考のために府中を追加し、対象日として2021年1月1日も追加。)
尚、各地点の地点番号等は、以下のページにまとめてあります。
https://script.google.com/macros/s/AKfycbxBEzysNCssxGOBLsI93SqwpPxdTFpRgvVvdFUvujkfBXX12cQ/exec
(Ctrl+Fで検索をかけると効率的かと思います。)
### Scraping Setting ###
pname=['Nerima','Fuchu']
pprec=['44' ,'44' ]
pblck=['1002' ,'1133' ]
pflag=['0' ,'0' ]
# Target date (with 8-digit yyyymodd)
dlist=['20200101','20210101']
このセッティングでは、「練馬と府中の両地点で2020年1月1日と2021年1月1日の気象データを取得する」ことになっています。
あとはpprec
等で設定した値をURLに埋め込めば対象のwebページに直接アクセスすることが出来ます。
## extraction date info
for k in dlist: # LOOP with Date
year = k[0:4] # year from dlist
month = k[4:6] # month from dlist
day = k[6:8] # day fromt dlist
dtag = k # date(tag) fromt dlist
## combine point info
for f, j, i, n in zip(pflag, pprec, pblck, pname): # LOOP with Points
flag = f
prec = j
blck = i
name = n
## URL
if flag == '0':
url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php?'\
'prec_no=' + str(prec) + '&block_no=' + str(blck) + \
'&year=' + str(year) + '&month=' + str(month) + '&day=' + str(day) + '&view=p1'
else:
url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?'\
'prec_no=' + str(prec) + '&block_no=' + str(blck) + \
'&year=' + str(year) + '&month=' + str(month) + '&day=' + str(day) + '&view=p1'
以上で今回のスクレイピングの対象となるURLの作成が完了しました。
##スクレイピング
スクレイピング自体は非常に簡潔に書けます。
対象のutl
のページ内のTable
をデータフレームdf
に格納します。
尚、連続してアクセスするとサーバーに余計な負荷をかけてしまうので、
毎アクセスに5秒以上の時間間隔を設定しています。
## scraping
tables = pd.io.html.read_html(url)
df = tables[0].iloc[:,1:] #row&col
df = df.reset_index(drop = True)
## Sleep
time.sleep(5)
##出力
出力設定
で用意したddir
にスクレイピングで獲得したデータをテキスト形式で出力します。
尚、ここではファイル名ofile
を地点名AMeDASyyyymodd.txtとしています。
## Output
ofile = str(ddir) + '/' + str(name) + 'AMeDAS' + str(dtag) + '.txt'
with open(ofile,'w') as f:
print('This file was downloaded at: ', datetime.now(), '(in UTC)', file=f)
print('*time* 0 = 00:10 and 143 = 24:00', file=f)
print('point: ', str(name), file=f)
print('date: ', str(dtag), file=f)
print('URL: ', str(url), file=f)
print('', file=f)
print(df, file=f)
以上で出力が完了します。
あとは地点・日時でループをまわすだけです。
#ソースコード
以上の各セクションを結合したものが以下のソースコードです。
コピーしてGoogle Colaboratoryにペースト・実行すればすぐにデータを取得できます。
###++++++++++++++++++++++++++++++++++++++++++###
### Creater: kogetaenoki on 2019/05/18 ###
###++++++++++++++++++++++++++++++++++++++++++###
### reference: https://met-learner.hatenablog.jp/entry/2019/12/15/123637
###+++++
### Import Libraries ###
from google.colab import drive
from datetime import datetime
import numpy as np
import pandas as pd
import time
import os
### Mount own drive ###
# Your permission are required when 1st time
# after the 1st time, add "#" to head of following command, available.
# (Nothing wrong with not doing it)
drive.mount('/content/drive')
### output folder name ###
# MyDrive/"odir"
odir = 'data/point'
### output option ###
pd.set_option('display.max_rows',150)
### Scraping Setting ###
pname=['Nerima','Fuchu'] #Site name
pprec=['44' ,'44' ] #Area No.
pblck=['1002' ,'1133' ] #Site No.
pflag=['0' ,'0' ] #Site type
# Target date (with 8-digit yyyymodd)
dlist=['20200101','20210101']
###============================###
### Hereafter, DO NOT DISTURB! ###
###============================###
## prepare the folder
%cd '/content/drive/MyDrive'
cdir = os.getcwd()
ddir = str(cdir) + '/' + odir
print(ddir)
if not os.path.exists(ddir): os.makedirs(ddir)
## extraction date info
for k in dlist: # LOOP with Date
year = k[0:4] # year from dlist
month = k[4:6] # month from dlist
day = k[6:8] # day fromt dlist
dtag = k # date(tag) fromt dlist
print ('get_data: ',year,'/',month,'/',day)
## combine point info
for f, j, i, n in zip(pflag, pprec, pblck, pname): # LOOP with Points
flag = f
prec = j
blck = i
name = n
## URL
if flag == '0':
url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/10min_a1.php?'\
'prec_no=' + str(prec) + '&block_no=' + str(blck) + \
'&year=' + str(year) + '&month=' + str(month) + '&day=' + str(day) + '&view=p1'
else:
url = 'http://www.data.jma.go.jp/obd/stats/etrn/view/10min_s1.php?'\
'prec_no=' + str(prec) + '&block_no=' + str(blck) + \
'&year=' + str(year) + '&month=' + str(month) + '&day=' + str(day) + '&view=p1'
print ('point: ', name, ', date: ', dtag)
## scraping
tables = pd.io.html.read_html(url)
df = tables[0].iloc[:,1:] #row&col
df = df.reset_index(drop = True)
## col_name
if flag == '0':
df.columns = ['PRC','TEMP','WS_MEAN','WD_MEAN','WS_GUST','WD_GUST','SUN']
else:
df.columns = ['PRES','SLP','PRC','TEMP','RH','WS_MEAN','WD_MEAN','WS_GUST','WD_GUST','SUN']
## Sleep
time.sleep(1)
## Output
ofile = str(ddir) + '/' + str(name) + 'AMeDAS' + str(dtag) + '.txt'
with open(ofile,'w') as f:
print('This file was downloaded at: ', datetime.now(), '(in UTC)', file=f)
print('*time* 0 = 00:10 and 143 = 24:00', file=f)
print('point: ', str(name), file=f)
print('date: ', str(dtag), file=f)
print('URL: ', str(url), file=f)
print('', file=f)
print(df, file=f)
print ('Done all.')
#参考
はじめての気象データ処理(met_learner様), 気象庁アメダス10分間値をダウンロードする方法, https://met-learner.hatenablog.jp/entry/2019/12/15/123637