無料天気予報APIのOpenWeatherMapを使ってみる

# はじめに
プログラムから天気予報をとるために、無料で開発者用APIを提供している[OpenWeatherMap](http://openweathermap.org/)を使ってみました。

# 概要
OpenWeatherMapはAPIだけのサービスというわけではなくGUIでも天気を取得できます。トップページにデカデカ「Current weather and forecasts in your city」と書いてあり、地名を入れると天気予報を表示してくれます。

<img width="1079" alt="スクリーンショット 2016-03-03 0.09.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/43208/cd624fab-3e58-cd45-0ebf-cfafa32174e8.png">

これは普通に便利ですね :sunny:

とは言いつつもメインはAPIみたいです。APIを使うには登録してAPI Keyを取得する必要があります。

# 値段
無料プランを始めとして、いくつか[プラン](http://openweathermap.org/price)があります。

無料のFreeプランだと5日後までの3時間毎の天気予報を取得できて、1分間に60回までAPIコールできます。月180ドルのDeveloperプランでは3000 calls/分までOKで、16日後までの天気予報を取得することができます。

# API Keyの取得
API Keyを取得するにはアカウントを作る必要があります。[Sign Upページ](http://home.openweathermap.org/users/sign_up)で必要な項目を入力して「Create Account」します。

<img width="488" alt="スクリーンショット 2016-03-03 0.20.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/43208/beac4bfd-77ba-2844-86e1-73b23181b203.png">

そうすると次の画面でAPI Keyが表示されるはずです。

# 天気予報を取得する
Rubyで天気予報を取得してみます。単純にAPIを試してみたいだけなら全然まったくRubyである必要はなく、`curl`コマンドとかを使った方が簡単だと思います。

基本は`api.openweathermap.org/data/2.5/forecast`というエンドポイントにパラメータを付け足してリクエストします。

## 都市名を指定する
まずは都市名を指定して天気予報を取得してみます。
都市は`q`というパラメータで指定します。API Keyは`APPID`というパラメータで指定します。

```ruby
API_KEY = "YOUR API KEY"
BASE_URL = "http://api.openweathermap.org/data/2.5/forecast"

require "json"
require "open-uri"

response = open(BASE_URL + "?q=Akashi-shi,jp&APPID=#{API_KEY}")
puts JSON.pretty_generate(JSON.parse(response.read))
```

明石焼きが食べたい気分なので明石を指定してみました。実行結果は次のようになります。

```json
{
  "city": {
    "id": 1850924,
    "name": "Takatorichō",
    "coord": {
      "lon": 135.133331,
      "lat": 34.650002
    },
    "country": "JP",
    "population": 0,
    "sys": {
      "population": 0
    }
  },
  "cod": "200",
  "message": 0.0272,
  "cnt": 34,
  "list": [
    {
      "dt": 1456941600,
      "main": {
        "temp": 277.58,
        "temp_min": 273.421,
        "temp_max": 277.58,
        "pressure": 1022.93,
        "sea_level": 1038.49,
        "grnd_level": 1022.93,
        "humidity": 71,
        "temp_kf": 4.15
      },
      "weather": [
        {
          "id": 800,
          "main": "Clear",
          "description": "clear sky",
          "icon": "01n"
        }
      ],
      "clouds": {
        "all": 0
      },
      "wind": {
        "speed": 3.67,
        "deg": 239.002
      },
      "rain": {
      },
      "snow": {
      },
      "sys": {
        "pod": "n"
      },
      "dt_txt": "2016-03-02 18:00:00"
    },
    ...
  ]
}
```

Takatorichōってのがどこかわかりませんが、経度が[135度](https://ja.wikipedia.org/wiki/%E6%97%A5%E6%9C%AC%E6%A8%99%E6%BA%96%E6%99%82%E5%AD%90%E5%8D%88%E7%B7%9A)になってるのでだいたい明石付近の天気はとれてるようです。多分。

`list`プロパティの値が配列になっていて、3時間ごとの天気予報が格納されています。
レスポンスの細かい内容は[ドキュメント](http://openweathermap.org/current#parameter)を参照してください。

## city IDを指定する
このように`q`パラメータで都市名を指定すると曖昧性があるので、OpenWeatherMapはcity IDというものでリクエストすることを推奨しています。
city IDの一覧は次のURLからダウンロードできます。`city.list.json.gz`ですね。3.8MBあります。

http://bulk.openweathermap.org/sample/

残念ながら明石のcity IDはないらしいので、かわりに神戸の天気予報をcity IDで取得してみます。神戸のcity IDは`1859171`です。

city IDは`id`パラメータで指定します。

```ruby
# 省略
response = open(BASE_URL + "?id=1859171&APPID=#{API_KEY}")
puts JSON.pretty_generate(JSON.parse(response.read))
```

結果は載せませんが、うまく取得できてるみたいです。

## 緯度経度を指定する
明石の天気予報が取れないままでは悔しいので緯度と経度を指定して天気予報を取得してみます。

[天文科学館](http://www.am12.jp/)の緯度と経度を指定します。天文科学館は[Wikipedia](https://ja.wikipedia.org/wiki/%E6%98%8E%E7%9F%B3%E5%B8%82%E7%AB%8B%E5%A4%A9%E6%96%87%E7%A7%91%E5%AD%A6%E9%A4%A8)によると北緯34度、東経135度にあります。

緯度は`lat`、経度は`lon`パラメータで指定できます。

```ruby
# 省略
response = open(BASE_URL + "?lat=34&lon=135&APPID=#{API_KEY}")
puts JSON.pretty_generate(JSON.parse(response.read))
```

さあどうでしょう。

```json
{
  "city": {
    "id": 1848131,
    "name": "Yuasa",
    "coord": {
      "lon": 135.183334,
      "lat": 34.033329
    },
    "country": "JP",
```

うーーーん、どこやねん。

## 郵便番号を指定する
まだまだ諦められません。最後に郵便番号を指定してみます。これなら間違いないはず！

郵便番号は`zip`パラメータに郵便番号と国コードを指定します。

天文科学館がある人丸町の郵便番号である673-0877を指定します。

```ruby
# 省略
response = open(BASE_URL + "?zip=673-0877,JP&APPID=#{API_KEY}")
puts JSON.pretty_generate(JSON.parse(response.read))
```

結果は…。

```json
{
  "city": {
    "id": 1847966,
    "name": "Akashi",
    "coord": {
      "lon": 134.983337,
      "lat": 34.633331
    },
    "country": "JP",
```

やった！！ついに取れました！！:joy::sparkles:
なんとcity IDもわかったのでこれからは苦労することなくcity IDで明石の天気予報を取得することができます。

# おわりに
OpenWeatherMapを使うととても簡単に天気予報をとってくることができます。
天気を予報したいときにいかがでしょうか。