OpenWeatherMapをショートコードにして各地の天気を表示

この記事は約19分で読めます。

Image

OpenWeatherMapを利用して天気情報を取得してみる、でOpenWeatherMapというAPIを使って八王子の天気を表示出来るかどうか、実験してみました。大体はできたのですが、もちょっと汎用的にしたり、表示を分かりやすくしてみたのでそれについて書きます。

スポンサーリンク

天気と天気詳細の日本語化をする

OpenWeatherMapで戻ってくるお天気情報は英語です。例えば 晴れ なら Clear とか、くもり なら Clouds とかが返ってきているようです。プログラムにする場合はこれらの英語に対する日本語を指定しておけばOKです。しかし、そういうときプログラムなので 全部の種類 が分かっていないとだめなのです。だめ、というのは4種類しかないと思って4種類分の日本語を用意していても、5種類目が実はあって、という場合に対応する日本語を用意していないために日本語で表示出来なくなってしまいます。

前回、そうおもって全種類を調べたのですがみつかりませんでした。かといって、やはり、お天気ウィジェットをもちょっとすすめたいし、、と思ったのでとりあえず分かっている種類だけの日本語を用意してそれ以外のお天気が来たらそのまま(英語のまま)表示、ということにしました。

今分かってる種類はこんな感じです

    $inEnglish = array('clear', 'clouds', 'rain', 'snow');
    $inJapanese = array('晴れ', 'くもり', '雨', '雪');

少なすぎる、、他にもありそうですが(^_^;、まぁ今のところこんなかんじでやっております。

お天気詳細の方は一覧がみつかりました!

Image

Weather condition codes

OpenWeatherMapのAPIで取得した値をjson_decodeして$weatherという値に入れた場合は、

Image [1]

$weather['weather'][0]['id']

にこの表で言う ID が入っています。そのIDで日本語を表示させることができそうです。

Image [2]

とてもたくさんあるのでchromeで自動翻訳してみました。

Image [3]

これをコピーして、Excelに貼り付けます。翻訳でところどころ意味の分からないところがあってので微調整します。Dの列に関数を入れて、PHPコードにして、、、D列をコピーして

    $description[200] = '小雨と雷雨';
    $description[201] = '雨と雷雨';
    $description[202] = '大雨と雷雨';
    $description[210] = '光雷雨';
    $description[211] = '雷雨';
    $description[212] = '重い雷雨';
    $description[221] = 'ぼろぼろの雷雨';
    $description[230] = '小雨と雷雨';
    $description[231] = '霧雨と雷雨';
    $description[232] = '重い霧雨と雷雨';
    $description[300] = '光強度霧雨';
    $description[301] = '霧雨';
    $description[302] = '重い強度霧雨';
    $description[310] = '光強度霧雨の雨';
    $description[311] = '霧雨の雨';
    $description[312] = '重い強度霧雨の雨';
    $description[313] = 'にわかの雨と霧雨';
    $description[314] = '重いにわかの雨と霧雨';
    $description[321] = 'にわか霧雨';
    $description[500] = '小雨';
    $description[501] = '適度な雨';
    $description[502] = '重い強度の雨';
    $description[503] = '非常に激しい雨';
    $description[504] = '極端な雨';
    $description[511] = '雨氷';
    $description[520] = '光強度のにわかの雨';
    $description[521] = 'にわかの雨';
    $description[522] = '重い強度にわかの雨';
    $description[531] = '不規則なにわかの雨';
    $description[600] = '小雪';
    $description[601] = '雪';
    $description[602] = '大雪';
    $description[611] = 'みぞれ';
    $description[612] = 'にわかみぞれ';
    $description[615] = '光雨と雪';
    $description[616] = '雨や雪';
    $description[620] = '光のにわか雪';
    $description[621] = 'にわか雪';
    $description[622] = '重いにわか雪';
    $description[701] = 'ミスト';
    $description[711] = '煙';
    $description[721] = 'ヘイズ';
    $description[731] = '砂、ほこり旋回する';
    $description[741] = '霧';
    $description[751] = '砂';
    $description[761] = 'ほこり';
    $description[762] = '火山灰';
    $description[771] = 'スコール';
    $description[781] = '竜巻';
    $description[800] = '晴天';
    $description[801] = '薄い雲';
    $description[802] = '雲';
    $description[803] = '曇りがち';
    $description[804] = '厚い雲';

PHPに貼り付けました。これで翻訳は完成です。

風向きの日本語化をする

風向きを表示したいと思いました。しかし、OpenWeatherMapから返ってくる風向きは

  ["wind"]=>
  array(2) {
    ["speed"]=>
    float(1.66)
    ["deg"]=>
    float(51.0011)
  }

こんな感じで、deg(度)で返ってきます。この場合は、51.0011度、のようです。これを東西南北とかの方位に置き換えるにはどうしようか、、ググりました。

Wikipedia 方位

こちらに方位と角度の関係が載ってました

方位の表現
360°式
平面上では、北を基準とした角度で表現し、値を読み上げる方式が多く用いられる。この方式では、北を0° = 360°として時計回りに、東を90°、南を180°、西を270°とする、このように決められた水平面内での角度を方位角と呼ぶ。

なっ、なるほど。これを元に方位を計算すれば良さそうです。あまり細かくしたくなかったので8方位にして45度ずつ振り当てました。その部分のコードがこんな感じです。

    $kazamuki = _ryusWehatherWindDigree($weather['wind']['deg']);

(中略)
function _ryusWehatherWindDigree($digree){
    $windDigree = array();
    $windDigree['北'] = array(337.5, 382.5);
    $windDigree['北東'] = array(22.5, 67.5);
    $windDigree['東'] = array(67.5, 112.5);
    $windDigree['南東'] = array(112.5, 157.5);
    $windDigree['南'] = array(157.5, 202.5);
    $windDigree['南西'] = array(202.5, 247.5);
    $windDigree['西'] = array(247.5, 292.5);
    $windDigree['北西'] = array(292.5, 337.5);
    if($digree < 22.5){
        $digree += 360;
    }
    foreach($windDigree as $kazamuki => $fromTo){
        if(($fromTo[0] <= $digree) AND ($digree < $fromTo[1])){
            return $kazamuki;
            break;
        }
    }
    return '';
}

範囲をfromとtoの間、みたいに判定したかったので北の時の角度を +360 してあります。
これでdeg(度)に対する東西南北の風向きがわかるようになります。

これで、51.0011度は 北東 ということになります。

お天気マークの修正

元々ちょっと気になっていたのはお天気マークです。太陽のマーク昼用夜用があります。

Image [5]

夜の太陽は茶色い、と。ちょっとわかりにくいけどまぁいいかなと思っていたのですが、天気を表示させてみて昼間なのに夜の太陽になっていることにきづきました。

OpenWeatherMapのページで天気を見るところで確認すると

Image [4]

このように、グラフの天気は昼の太陽なのに、左側に出ているのは夜の太陽です。APIで戻ってくるアイコン名もどうやらこの左側の方の値なのでは無いかと思いました。このOpenWeatherMapを提供しているところはイギリス(というかなんというか)のようなので、グリニッジ標準時日本は+9時間なので時差を考慮してグラフのお天気マークは表示されているようですが、左側の方はグリニッジ標準時からのマークになってるようです。

どちらにしても夜の太陽は茶色い、というのがわかりにくかったので

$icon = str_replace('n', 'd', $weather['weather'][0]['icon']);

こういう感じでアイコンを全部昼用のものにしてしまいました。これで時差も関係ないです(^_^;。

ショートコードで便利に表示できるように修正する

前回は 八王子の天気 としていたのですが、今回ちゃんとしたショートコードにするために「都市名と国名」を指定して表示出来るようにしました。でも国名はたいがい日本なので何も指定しなければ日本に、また八王子優先コードとして(^^;、都市名を指定しなければ八王子の天気が表示されます(^^;。

ショートコードとして

[ryus_weather]

だけを指定すれば八王子の天気。

[ryus_weather city="Naha-shi"]

とかにすれば沖縄の那覇の天気。

[ryus_weather city="New York" country="US"]

とすればアメリカ合衆国ニューヨークの天気となります。

都市名や国名は OpenWeatherMap のページでsearchをして検索出来た名前にします。
 

こんな感じのものができました

コードは使っている子テーマのfunctions.phpに以下を追加しました。

// 今の天気を表示する
function ryus_weather($atts) {
    /* 引数を展開する */
    extract(
        shortcode_atts(
            array(
                'city' => 'Hachioji',
                'country' => 'jp',
                'appid' => '',
            ),
            $atts
        )
    );
    // 天気の表示用html 適宜変更しましょう
    // 確認のため、都市名をdisplay:noneでコーディングしてあるので必要があれば表示してみてください
    $weatherShow = '
    <div class="ryusWheather">
    <div style="display:none">%s</div>
    <div style="text-align:center;font-weight:bold;">%s</div>
    <div><img src="http://openweathermap.org/img/w/%s.png" style="width:200px"></div>
    <div>温度:%s 度</div>
    <div>湿度:%s パーセント</div>
    <div>風:%sメートル(%s)</div></div>';

    $url = sprintf('http://api.openweathermap.org/data/2.5/weather?q=%s,%s&units=metric&appid=%s', $city, $country, $appid);
    $weather = json_decode(file_get_contents($url), true);
    
    // openweathermapで取得した全ての値を見たいときは下のコメントを外して投稿や固定ページでショートコードを表示してみてください。
    //echo "<pre>";var_dump($weather);echo "</pre>";
    
    // tenki は 晴れ、曇、雨、雪 です。現在のコードでは表示してません。表示したいときは $tenkiを使ってください
    $tenki = _ryusWheatherTranslate($weather['weather'][0]['main']);
    $kazamuki = _ryusWehatherWindDigree($weather['wind']['deg']);
    $description = _ryusWheatherDescription($weather['weather'][0]['id']);
    $temp = round($weather['main']['temp'], 1);
    $icon = str_replace('n', 'd', $weather['weather'][0]['icon']);
    // 天気の表示用html を変更したときは、この下の値設定も変える必要がある場合があります
    return sprintf($weatherShow, $weather['name'], $description, $icon, $temp, $weather['main']['humidity'], $weather['wind']['speed'], $kazamuki);
}

// 天気を日本語にする
function _ryusWheatherTranslate($main){
    $mainLower = mb_strtolower($main);
    $inEnglish = array('clear', 'clouds', 'rain', 'snow');
    $inJapanese = array('晴れ', 'くもり', '雨', '雪');
    $key = array_search($mainLower, $inEnglish);
    if ($key === false){
        return $main;
    } else {
        return $inJapanese[$key];
    }
}

// 天気詳細を日本語にする
function _ryusWheatherDescription($id){
    $description = array();
    $description[200] = '小雨と雷雨';
    $description[201] = '雨と雷雨';
    $description[202] = '大雨と雷雨';
    $description[210] = '光雷雨';
    $description[211] = '雷雨';
    $description[212] = '重い雷雨';
    $description[221] = 'ぼろぼろの雷雨';
    $description[230] = '小雨と雷雨';
    $description[231] = '霧雨と雷雨';
    $description[232] = '重い霧雨と雷雨';
    $description[300] = '光強度霧雨';
    $description[301] = '霧雨';
    $description[302] = '重い強度霧雨';
    $description[310] = '光強度霧雨の雨';
    $description[311] = '霧雨の雨';
    $description[312] = '重い強度霧雨の雨';
    $description[313] = 'にわかの雨と霧雨';
    $description[314] = '重いにわかの雨と霧雨';
    $description[321] = 'にわか霧雨';
    $description[500] = '小雨';
    $description[501] = '適度な雨';
    $description[502] = '重い強度の雨';
    $description[503] = '非常に激しい雨';
    $description[504] = '極端な雨';
    $description[511] = '雨氷';
    $description[520] = '光強度のにわかの雨';
    $description[521] = 'にわかの雨';
    $description[522] = '重い強度にわかの雨';
    $description[531] = '不規則なにわかの雨';
    $description[600] = '小雪';
    $description[601] = '雪';
    $description[602] = '大雪';
    $description[611] = 'みぞれ';
    $description[612] = 'にわかみぞれ';
    $description[615] = '光雨と雪';
    $description[616] = '雨や雪';
    $description[620] = '光のにわか雪';
    $description[621] = 'にわか雪';
    $description[622] = '重いにわか雪';
    $description[701] = 'ミスト';
    $description[711] = '煙';
    $description[721] = 'ヘイズ';
    $description[731] = '砂、ほこり旋回する';
    $description[741] = '霧';
    $description[751] = '砂';
    $description[761] = 'ほこり';
    $description[762] = '火山灰';
    $description[771] = 'スコール';
    $description[781] = '竜巻';
    $description[800] = '晴天';
    $description[801] = '薄い雲';
    $description[802] = '雲';
    $description[803] = '曇りがち';
    $description[804] = '厚い雲';
    if (array_key_exists($id, $description) === false) {
        return $id;
    }
    return $description[$id];
}

// 風向きを表現する
function _ryusWehatherWindDigree($digree){
    $windDigree = array();
    $windDigree['北'] = array(337.5, 382.5);
    $windDigree['北東'] = array(22.5, 67.5);
    $windDigree['東'] = array(67.5, 112.5);
    $windDigree['南東'] = array(112.5, 157.5);
    $windDigree['南'] = array(157.5, 202.5);
    $windDigree['南西'] = array(202.5, 247.5);
    $windDigree['西'] = array(247.5, 292.5);
    $windDigree['北西'] = array(292.5, 337.5);
    if($digree < 22.5){
        $digree += 360;
    }
    foreach($windDigree as $kazamuki => $fromTo){
        if(($fromTo[0] <= $digree) AND ($digree < $fromTo[1])){
            return $kazamuki;
            break;
        }
    }
    return '';
}

/* ショートコードを追加する */
add_shortcode('ryus_weather', 'ryus_weather');

長いですね(^_^;。classとかだったらもちょっといい感じに書けたかもしれないんですが。。あと、ウィジェットに表示するため、バックカラーとかをCSSで指定しました

/* ryusWheather */
.ryusWheather {
    background-color:#fff;
    color:#000;
    padding:10px;
}

これを使っている子テーマの style.css に追加しました。

ということで、ウィジェットに

Image [6]

こんな感じで指定すると、

Image [7]

こんな感じで表示されるようになりました(^^)/。

ニューヨークって寒いんですねー

appidを指定しよう

コーディングしているのですがついつけるのを忘れてしまうのがappidです。このAPIを使うにはappidを指定する事、とあります。現在上記のようにappidが空欄でも取得はできているのですが、ちゃんとした使い方で無いためいつ利用ができなくなるかもしれません。

How to start to work with Openweather API - OpenWeatherMap
It is quite easy to work with Openweather API. Just sign up to get your API key and then call any weather API. And mind using API key in every API call whatever...

こちらで取得したappid

<div style="font-weight:bold;">八王子</div>
[ryus_weather appid="取得したappid"]

<div style="font-weight:bold;">那覇</div>
[ryus_weather city="Naha-shi" appid="取得したappid"]

<div style="font-weight:bold;">ニューヨーク</div>
[ryus_weather city="New York" country="US" appid="取得したappid"]

こんな感じで指定してお使いくださいm(_ _)m。

まとめ:OpenWeatherMapのいいところとこれがあったらいいなぁ

このOpenWeatherMapのいいところは都市名ぐらいの単位で天気を取得することができるというところです。他のAPIを見てみたのですがわりとおおざっぱなものしか見つかりませんでした。また、今回のように都市名、国名ではなく緯度、経度でも lat=緯度&lon=経度 で指定できます。

また、5日分は3時間単位、1日単位だと16日分の天気予報が取得できるようです。まだまだ色々な表示ができそうですね。

これがあったらいいなぁというのが 「降水確率」 です。これって日本独特なんでしょうか?湿度や気圧が返ってくるのでその辺から降水確率がわかるのかな?ちょっと今時点では不明です。

今時点ではこのOpenWeatherMapが情報も多くてよいなぁと思うのでまたもっと色々な表現をしてみたいなと思います。

兎本美佳

ブログを見た人がそのままできたらいいなと思って、できるだけ丁寧に書いています。blogに書いたようなネタの有償対応のご相談は「ゆうそうと」へいただければと思います(^^)/
無償での対応をご希望の場合は、コメントをいただけましたら可能な場合はコメントを返させていただきます。

ゆうそうとITブログの更新通知が受け取れます!
スポンサー広告

インターネット オープンソース オープンデータ API
スポンサーリンク
ゆうそうとITブログの更新通知が受け取れます!
ゆうそうとITブログ

コメント

  1. 今OpenWeatherMapのlocalizationに「日本語」を足して欲しい、という話を投げていて、
    Excelで訳語を送って欲しいと言われています。
    この記事にある訳語を使わせていただいても良いですか?

  2. 小雨の訳とか色々修正が必要そうなので、参考資料として使用させていただきます。

    • 兎本美佳兎本美佳 より:

      おはようございます、toowitterさん。なにかお役に立つようでしたらどうぞご自由にお使いください(^^)/

  3. ロト君 より:

    丁度、調べたい情報でした!もう少し勉強したいと、思います!!

    ありがとうございます!!

    • 兎本美佳兎本美佳 より:

      ロト君さん、こんにちは!コメントありがとうございます。なにかお役に立てたようなら幸いです。最近はプラグインで、 https://usortblog.com/weather_in_japan/ こういうのもあるみたいです。コーディングがめんどうでしたらこちらでもいいかもですー

トップへ戻る

ゆうそうとについての説明

ゆうそうと とは東京都八王子市を中心として、WordPressによるWEBサイトの作成や、スポットでのIT相談を行ったり、年間契約でのIT顧問をなりわいとして活動しています。

特徴としては30年以上IT業界でプログラムを中心として仕事をしてきたものと、美大出身のデザイナーがワンストップで対応するため、幅広い対応が可能であることです。

IT相談は直接お会いしてのご相談の他、ZOOMによるオンライン相談も可能です。