Ruby 天気予報編 (7) 天気予報 API へのアクセス 【計算数学 I】
更新日時:
天気予報 API へのアクセス
準備が終わり、やっと本題に入リます。天気予報 API を利用する段階にきました。
今回は Weather Hacks を使用します。 Hash を知り、 JSON を知った我々にとって、残る問題は、以下の 2 つです。
- 今回使用する API の仕様はいかなるものか
- Ruby で API にどうやってアクセスし、返り値を受け取るか
前者は、 Ruby の話ではありません。サービスを提供する側が決めた仕様を調べ、理解し、それに合わせて我々が実装するのみです。後者については、いくつか方法があります。前作の教材で open-uri
モジュールを使ったので、今回はこれでいきます。
API の仕様 (リクエスト側)
今回の API の仕様書は
に書かれている通りです。仕様はサービスを提供する人が決めることなので、私が説明することはありません。これを読むしかないです。単純な API なので読めばすぐわかると思いますが、概要を箇条書きにします。
- 情報を受け取るには、指定された URL にアクセスする。
- URL の末尾には、我々が「リクエストを付与」する。今回の場合は、地域を番号で指定する。指定の仕方は自分でみる。例も挙げられている。
これは Ruby の練習ですから、ひとまず自分の好きな地域を 1 つ決めましょう。確認のためブラウザで URL にアクセスしてみましょう。JSON がブラウザに表示されていれば、このセクションはクリアです。
Ruby で URL にアクセスするには
今度は Ruby で URL に「アクセス」してみましょう。
API を利用すると言っても、結局 URL を指定して情報をダウンロードするだけですので、前回もやったように open-uri
ライブラリを使って Kernel.#open
でアクセスすればよいです。open についてこちらとこちらに書きました。
前回説明していなかったこと: URL でアクセスした情報を文字列として受け取る際は read
を使用します(StringIO#read
)。例えば、
json = ""
open(url){|input|
json = input.read
}
のようにすると、url
にアクセスした先の情報を文字列として json
に受け取ることができます。事前に json = ""
としているので、ブロックの外で失われることはありません。
API の仕様 (返り値側)
返り値についても
に書かれている通りです。 JSON.parse
でそのまま Hash に変換されます。
以下の説明では hash
にこの JSON を変換したものが入っているとします。
天気予報 API は好きなように使えばよいと思います。好きなように使うヒントを述べておきます。
JSON.parse
で変換したハッシュのキーは全て「文字列」です。シンボルではありません。hash["forecasts"]
は予報日毎に 配列 になっています。今日の天気にアクセスするならばhash["forecasts"][0]
とアクセスする必要があります。- 最低気温、最高気温は空欄の可能性があります。次のセクションで、空欄の判定法を解説しています。
空欄の取り扱い
ある JSON を Hash にしたものを hash
にいれているとします。
hash[key]
で key
に対応する値が返ります。
ここでもし、以下の場合が起きたらどうなるでしょうか。
- JSON 側で
key
に対応する項目がそもそもない - JSON 側で
key
に対応する項目は空欄である(注意:「空欄」と「空文字」は異なる)。
Ruby では、この場合、 hash[key]
は nil
を返します。
nil
は Nil
クラスの唯一のインスタンスで、プログラム中どこで nil
と書いても同じものを指します。さしあたっては「空欄」や「ないもの」を表すオブジェクトだと思っておけばよろしいです。
あるオブジェクトが nil
であるかどうかを判定するメソッドは nil?
です。返り値は true
または false
です。
以上を総合すると、 メソッド nil?
を使うことにより、JSON の返り値が空欄かどうかを判定ができる ということになります。特に Ruby では、これは特徴的な考え方となっています。
API の利用規約
一般論になりますが、 API を利用する際は、利用規約をよく読みましょう。特に、以下の項目は重要です。
- 料金が発生するのか
- 今回は無料。
- ユーザー認証が必要か
- 今回は必要ない。
- どの程度の頻度でアクセスしてよいのか
- ループしたり自動化したりして、アクセスの頻度が高くなりすぎると、返り値が返ってこないばかりか攻撃となりえる。
- 今回はまず問題なかろう。
- 利用用途に制限はあるか
- 今回はこれが重要。
Wether Hacks の Q&A を見ると、以下のように書かれています。
Q Weather Hacksの商用利用は可能でしょうか?
A 本サービスの情報を利用した、商用活動はご遠慮下さい。また、Weather Hacksが提供するデータは個人的な範囲でのご利用に留めて頂くようお願い致します。
今回は「Ruby の学習に使用する」のですから、商業利用ではありません。「Twitter で天気予報を試しに投稿する」が「個人的な範囲」を逸脱するかどうかは、一応議論の余地はあるかもしれませんが、先方から怒られることはないのではないでしょうか。
ここまでのプログラム
ここまでで、 Twitter に投稿する文章を作成することができるようになりました。標準出力に出してみましょう。ところどころ空欄にしています。
以下のプログラムでは、天気と、最高気温・最低気温を出力する文章にしてみましたが、皆さんは 自分の好きな項目 を文章にしましょう。ただし Twitter の投稿文は 140 字以内ですから、今のうちに、その文字数をオーバーしないような文章にまとめましょう。
コツ: 文章を練るときは、 irb を使うと楽 でしょう。具体的には、以下の require
と get_weather()
(もちろん空欄を埋めたもの) を irb にコピーアンドペーストして、 hash = get_weather()
のようにしておきます。その後、 API の仕様を irb で、例えば "#{hash["forecasts"][0]["dateLabel"]}の天気"
のように打ち込んでみます。すると「今日の天気」と返ってくるので、うまくいっていることがわかります。このようにしてプログラムを完成させていきます。
プログラム例
# coding: utf-8
require 'open-uri'
require 'json'
def get_weather()
json = ""
url = # 好きな地域の URL を入れる
open(url){|input|
json = input.read
}
# json を Hash に加工して return する。
end
def make_str(day)
# 説明文で言うところの hash["forecast"][0] や
# hash["forecast"][1] が引数の day に入る。
str = # 「今日の天気は晴れ」のような文字列をここに書く。
if # 最高気温欄が空欄でなければ
maxi = day["temperature"]["max"]["celsius"].to_i
str += "、最高気温は#{maxi}度"
end
# 最低気温についても同じことをする。
str += "です。"
return str
end
hash = get_weather()
ary = hash["forecasts"]
str = # 今日と明日の天気を結合する。
puts str + Time.now.strftime("(%H:%M:%S)") # 末尾に時刻を挿入してみた
出力例
今日の天気は晴時々曇、最高気温は30度です。明日の天気は雨、最高気温は23度、最低気温は20度です。(05:34:13)
ナビゲーション
この教材は、東京大学理学部数学科専門科目「計算数学 I」のために執筆されたものです。 このサイトに掲載する際に、記事を分けてあります。 他の回はRuby 天気予報編 一覧 #ks1-ruby-forecastから御覧ください。
Ruby 入門 (計算数学実習資料集)には他の TA が書いた教材があります。