今回の目的
職場の農業法人で25ha全43枚の畑の管理を任されていまして、枚数と種類が多すぎて作業の管理が不可能でした。
そこで、定植日からの積算温度(1日の平均気温を積算した値)一瞬で確認できるものがあれば便利だと思い作ってみました。
なにをするのか
こちらから情報を頂いてきます。天気予報のAPI(ぽいもの)は配信されているようですが、過去の気象データはこの表かcsv形式でしか配信されておりません。
この平均気温の行を取得してきて合計します。(0度以下は0として扱う)
Mechanizeを使ってスクレイピングします。
ソースコード
require "Mechanize"
require "Date"
def get_accum(prec_no, block_no, correct)
y_date = Date.yesterday #昨日
y_year = y_date.year
y_month = y_date.month
y_day = y_date.day
start_date = Date.new(開始日)
start_year = start_date.year
start_month = start_date.month
start_day = start_date.day
diff_month = y_month - start_month
if y_year == start_year #開始月と今月が同じ年でなければ差に+13、同じ年なら+1
term_month = diff_month + 1
else
term_month = diff_month + 13
end
ave_temps =[] #空の配列を作成して取得データを追加
term_month.times do |m|
if start_month + m > 12 #年を跨ぐとき
start_year += 1
start_month -= 12
end
url = "http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?prec_no=#{prec_no}&block_no=#{block_no}&year=#{start_year}&month=#{start_month + m}&day=1&view=" #daily_s1をa1に変えれば各地方局にも対応可能
agent = Mechanize.new
page = agent.get(url)
td_length = page.search("//*[@id='tablefix1']/tr").length-4 #td要素の上4つは項目なので、全td要素から4を引いた数がデータの数になる
if m == 0 #スタート月のデータ取得
(td_length-(start_day-1)).times do |i|
ave_temp = page.search("//*[@id='tablefix1']/tr[#{5+(start_day-1)+i}]").search('td')[6].inner_text #7番目のtdタグが日平均気温
ave_temps << ave_temp.delete("^0-9.-") #配列としてave_tempsに順に追加。たまに()がついてたりするので除去
end
elsif m == term_month - 1 #今月のデータ取得
y_day.times do |i|
ave_temp = page.search("//*[@id='tablefix1']/tr[#{5+i}]").search('td')[6].inner_text
ave_temps << ave_temp.delete("^0-9.-")
end
else #中間の月は全部取得
td_length.times do |i|
ave_temp = page.search("//*[@id='tablefix1']/tr[#{5+i}]").search('td')[6].inner_text
ave_temps << ave_temp.delete("^0-9.-")
end
end
end
total_temp = 0
ave_temps.each do |temp|
if temp.present? #配列に値があるときのみ計算
temp = temp.to_f + correct #ここで補正値計算
if temp <= 0 #0度以下はデータとして加算しない。
temp = 0
end
total_temp += temp
end
end
return total_temp.round(2)
end
長ったらしくて汚いですが。。。
term_month.times do |m|
...
end
で期間の月の数繰り返し
"http://www.data.jma.go.jp/obd/stats/etrn/view/daily_s1.php?prec_no=#{prec_no}&block_no=#{block_no}&year=#{start_year}&month=#{start_month + m}&day=1&view="
prec_noは県の番号。block_noは観測所の番号
現状daily_s1となっているblock_no=47xxxの観測点のみ対応で、これは7列目に平均気温が存在している。
daily_a1の観測点は項目が少ないので4列目にある。このあたり条件分けできればもっと細かい観測地に対応できます。
if m == 0
#開始月の処理:要素の数(その月の日数)ら開始日を引いたところから取得を開始
elsif m == term_month - 1
#最終月(この場合今月):初日から昨日の日付まで取得
else
#中間月:全部取得
end
てな感じで必要な分だけ取ってきます。
ave_temp = page.search("//*[@id='tablefix1']/tr[#{5+i}]").search('td')[6].inner_text
複雑ですが、id='tablefix1'の中に、tr要素が縦に積まれていて、td要素が横並びに入っている構造です。
なのでtrを5行目から順番に取得して、その中の7番目のtdを持ってこいという意味になります。
あとは配列ave_tempsに全部突っ込んで合計して完了!!
correct(補正値)は基準より寒いor暑いで設定できます。自分の畑は標高差あるので上と下で2〜3℃くらい差があります。
注意事項
平均気温はどう頑張っても1日に1回しか更新されないので処理回数に制限をかける等して、必要な時だけに留めましょう。