花粉の飛散量を取得する Ruby スクリプト
動機
ちょっと前に見かけていた記事ですが、自分も花粉症に苦しんでいるということもあり、Nadoka さんの IRC Bot に仕込もうと思って Ruby で書いてみました。 :-p
環境省が運用する花粉観測システム(はなこさん)では1時間毎の花粉飛散データが公開されています。 1時間毎に花粉飛散データが更新されるため外出のタイミングを決定するのに役立ちます。 プログラマであれば、このデータを cron で定期的に監視して警告メールを送ったり、Shell のプロンプトやemacs のミニバッファに表示させたい、と思うはずです。
そこで、この花粉観測システムはなこさんから花粉飛散データを取得する perl module を作成しました。
花粉情報にしか興味がなかったので、風向や風速情報はとっていません。ほんとは scraping したほうがよかったのかもしれませんが、そこも手を抜いちゃいました。
自分としては、Net::HTTP での Cookie の使い方と、Ruby 1.9 での Array#to_s の動きが勉強になったかな、と。
# Nadoka さんを Ruby 1.9 で動かしてるわけじゃないんですが、そのままポーティングするのも芸がなかったので、なんとなく 1.9 対応...
動作確認
東京の観測所は以下となります。今の季節はまだ、都内はさほどではないですが、多摩森林科学園の花粉量はハンパないです。
エリアコード | 観測所コード | 観測所 |
---|---|---|
3 | 51310200 | 東京都多摩小平保健所 |
3 | 51320100 | 独立行政法人森林総研多摩森林科学園 |
3 | 51300100 | 日本医科大学付属多摩永山病院 |
3 | 51300200 | 日本医科大学付属病院 |
12時時点で動かしてみたら、以下の結果でした。飛散量が 1000 を越えると相当危険らしいです。
# 自分は 100個未満の都市部でも、かなりむずがゆいですが...。
% ruby191 hanako.rb 51310200 3 最新の花粉飛散量は、32 [個/m3] 9 時の花粉飛散量は、24 [個/m3] % ruby191 hanako.rb 51320100 3 最新の花粉飛散量は、520 [個/m3] 9 時の花粉飛散量は、61 [個/m3] % ruby191 hanako.rb 51300100 3 最新の花粉飛散量は、86 [個/m3] 9 時の花粉飛散量は、20 [個/m3] % ruby191 hanako.rb 51300200 3 最新の花粉飛散量は、69 [個/m3] 9 時の花粉飛散量は、8 [個/m3]
Array#to_s の挙動
Ruby 1.8 では Array#join、Ruby 1.9 では Array#inspect と同じ動きになります。
% irb186 >> %w(a b).to_s => "ab" >> %w(a b).inspect => "[\"a\", \"b\"]" >> %w(a b).join => "ab" >> exit % irb191 >> %w(a b).to_s => "[\"a\", \"b\"]" >> %w(a b).inspect => "[\"a\", \"b\"]" >> %w(a b).join => "ab" >> exit
スクリプト
Ruby 1.9 じゃないと動きません。
プロキシの設定ができるようにしてますが、経由の必要がなければ適宜書きかえてください。
# coding: utf-8 require 'net/http' class Hanako Net::HTTP.version_1_2 PROXY_HOST = "xxx" PROXY_PORT = yyy HANAKO_BASE_HOST = "kafun.taiki.go.jp" attr_reader :kafun, :mst_code, :area_code def initialize(mst_code = "51300200", area_code = "3") @kafun = { } @mst_code = mst_code @area_code = area_code request_and_parse(mst_code, area_code) end def now now = @kafun.keys.sort.last @kafun[now] end private def request_and_parse(mst_code, area_code) cookie = nil Net::HTTP::Proxy(PROXY_HOST, PROXY_PORT).start(HANAKO_BASE_HOST) do |http| response, = http.get("/Hyou0.aspx?MstCode=#{mst_code}&AreaCode=#{area_code.rjust(2,"0")}") response.error! unless response.is_a? Net::HTTPOK cookie = response.get_fields("Set-Cookie").join.split(";").first end Net::HTTP::Proxy(PROXY_HOST, PROXY_PORT).start(HANAKO_BASE_HOST) do |http| response, = http.get("/Hyou2.aspx", "Cookie" => cookie) response.error! unless response.is_a? Net::HTTPOK parse(response) end end def parse(response) response.body.each_line do |line| if /<td><font size=\"2\">([0-9]*)時<\/font><\/td><td align=\"Right\"><font size=\"2\">([0-9]*)<\/font><\/td>/ =~ line.force_encoding("UTF-8") @kafun[$1.to_i] = $2.to_i end end end end # == how to use == hanako = Hanako.new ARGV[0], ARGV[1] puts "最新の花粉飛散量は、#{hanako.now} [個/m3]" puts "9 時の花粉飛散量は、#{hanako.kafun[9]} [個/m3]"