Rubyで南岳の気象データを読取る
槍ヶ岳の気象データが更新されなくなって悲しかったのですが 代わりに 南岳の気象データ が昨年(2011年)10月から提供されていました。 URLも規則的で、中身もちゃんとマーキングされたHTMLでしたので ちょこっとスクリプト書いてデータを読んで見ました。
この南岳の気象データサイトは特に冬場の北アルプスに行く方にはとても有用なサイトだと思います。
RubyでWebのデータを読んでCSVとして保存する
#! ruby -Ks # -*- mode:ruby; coding:shift_jis -*- $KCODE='s' require 'date' require 'csv' require 'kconv' require 'open-uri' require 'rubygems' require 'nokogiri' URI_base = 'https://www.yarigatake.co.jp/minamidake/weather.html?date=' d = Date.new(2011,10,9) today = Date.today CSV.open('minamidake.csv','w') do |csv| csv << ['日時','気温(℃)','湿度(%)','気圧(hPa)','雨量(mm)','風速(m/s)','風向き','日射量(Watts/m2)'] while( d < today) d_str = d.strftime("%Y%m%d\n") uri = URI_base + d_str html = Nokogiri::HTML(open(uri)) html.search('table[@id="weather-observation-table"]').each do |table| table.search('.//tr').each do |tr| line = tr.search('./td').map{|td| td.text.tosjis} if line.size > 0 t = d.strftime("%Y/%m/%d ") + "#{line[0]}:#{line[1]}" csv << [t]+line[2..8] end end end d += 1 end end
このスクリプトはruby 1.8.7用です。 このような作業にはFirefoxだとFirebugという拡張機能を入れて置くと便利です。
まず、最初にやることは南岳の気象データのWebページを観察することです。 URLのルールはdateパラメータで日付を渡す形式だと分ります。 なのでURLは日付を一日づつ増やしながら今日まで廻せば、今日までの全てのデータが簡単に取れます。
次にデータの部分を観察するとidが"weather-observation-table"のtableと成っています。 最初が時、次が分なので、これとデータの日付をくっつけた物を日時データとして取り出せば グラフ等を作る処理が楽ですから、csvにする時に加工して置くのが良いですね。 このような場合にはワザワザExcelにするよりもcsvでサクッとデータを取り出し それをExcelやOpenOffice.orgで加工する方が手間がかかりません。
方向性が決まったのでスクリプトにします。
-
必要なモジュールをrequireして置き、URLの基本部分を先に定義しておきます。
require 'date' require 'csv' require 'kconv' require 'open-uri' require 'rubygems' require 'nokogiri' URI_base = 'https://www.yarigatake.co.jp/minamidake/weather.html?date='
-
また、いつからの分を取り出すかの開始日をdにDateクラスの値としてセットします。
d = Date.new(2011,10,9)
-
todayに取り出す最終日(含まない)をセットします。ここではプログラム起動日の前日までを対象とします。
today = Date.today
-
出力用のCSVファイルを書込み用('w')としてオープンします。
CSV.open('minamidake.csv','w') do |csv|
-
CSVに項目名の行を書込みます。配列をそのまま書込めば自動的に変換してCSVの様式で書いてくれます。
csv << ['日時','気温(℃)','湿度(%)','気圧(hPa)','雨量(mm)','風速(m/s)','風向き','日射量(Watts/m2)']
-
whileで終了日判定をして廻します。
while( d < today)
-
uriに基本部にパラメータとして日付をつけたURIを生成します。
d_str = d.strftime("%Y%m%d\n") uri = URI_base + d_str
-
NokogiriはXMLやHTMLを解析してくれるライブラリです。
uriをopen-uriモジュールで拡張されたopenで開いて、NokogiriにHTMLデータとして渡します。
この行だけでInternetにアクセスして指定したページを読込んで解析してくれます。
proxyの下にいる場合にはもう少し手続きが必要ですがここでは割愛します。
html = Nokogiri::HTML(open(uri))
-
htmlという変数に取り出したNokogiriの解析結果のオブジェクトが入っていますので、
Nokogiriの機能がhtmlに対して使用できます。
Nokogiriのsearchを使いXPATHという形式で解析データからid属性が"weather-observation-table"のtableを取り出します。
計測されていない日の場合にはこのtableが無いので以下の処理はしません。
searchは見つかったオブジェクトの配列を返します。見つからなければ空配列が返ります。
html.search('table[@id="weather-observation-table"]').each do |table|
-
そのテーブルの下を更にsearchでtrを探します。
table.search('.//tr').each do |tr|
-
さらにtrの下のデータが入っているtdを取り出します。
取り出し時はNokogiriのデータは全てUTF-8と成っているのでSJISに変換して置きます。
trの下には項目名のthの部分も有りますがその場合にはtdが無いので結果は空の配列となります。
mapは配列の各要素を「ブロックで渡された手続きで評価し」その結果を集めた配列を返します。
この場合には、各tdオブジェクトに対してtextという手続きを実施して文字列部分を取り出し、
更にSJIS変換した文字列の配列としてデータを返します。
line = tr.search('./td').map{|td| td.text.tosjis}
-
結果のサイズが0の場合には項目名の部分ですから無視します。
if line.size > 0
-
対象の日付とlineデータ内の(時、分)の部分で日時データを作ります。
t = d.strftime("%Y/%m/%d ") + "#{line[0]}:#{line[1]}"
-
作った日時データと残りのデータを足して、ひとつの配列としてCSVに書込みます。
csv << [t]+line[2..8]
-
d += 1 は日付クラスのデータですので日付として次の日を計算してくれます。
end end end d += 1 end end
Excelグラフ操作 ← : 南岳気象データ : → Excelマクロの操作
お勧めのRuby開発環境
Trail4You 仮想マシンバザール : Ruby統合開発環境仮想マシン上にruby統合開発環境をインストールしてあります。 rvm, git もインストール済みで各種rubyを切替ながら試せます。