アラタナエンジニアブログ

aratana Engineer's Blog

【Weather Hacks】毎朝お天気お姉さんから天気予報メールが届くドキドキプログラムを作ってみた。

こんにちは、開発の甲斐です。

「今日もいい天気☆」
そんな日に限って帰るときはだいたい雨です。宮崎県は最近そんな日が多くてホント困ります…。

ある雨の日の会社帰り、びしょ濡れになりながらふと思いつきました。
「毎朝天気予報メールが届けば、傘を忘れること無いんじゃないかな…!?」
ということで…

毎朝天気予報メールが届くPHPプログラムを作ってみました。

Q.天気予報の情報はどこから取ってくるの?
A.Weather Hacksという天気予報APIで取得できます。

Weather Hacksとは?

livedoorが提供している天気予報APIです。全国各地の天気予報を取得できます。
商用利用は不可、個人的な範囲の使用は許可されています。

使い方はとても簡単です。
以下のURLにたいしてcityパラメータを加えてリクエストを送ってあげるだけで天気予報JSONが返ってきます。
http://weather.livedoor.com/forecast/webservice/json/v1

パラメータ 説明
city 取得したい地域のID。各地区のIDはWeather Hacksでご参照ください。

天気予報JSONを取得する関数を作成

まずはじめに天気予報JSONを取得する関数を作ってみます。

<?php
$wh = new WeatherHacksMail();
var_dump($wh->getWeatherHacksJson(450010));

class WeatherHacksMail{
    public function getWeatherHacksJson($city_id) {
        $url = "http://weather.livedoor.com/forecast/webservice/json/v1?city={$city_id}";
        if (false === $data = @file_get_contents($url)) {
            return false;
        }
        return json_decode($data);
    }
}

getWeatherHacksJson関数へ地域IDを渡してあげると、指定した地域の天気予報JSONを返してくれます。(取得できなかった場合はFALSEを返す。)

今回は宮崎県・宮崎市(地域ID=450010)の天気予報を取得してもらいました。
実行すると以下のURLの内容と同じ内容が返ってきます。
http://weather.livedoor.com/forecast/webservice/json/v1?city=450010

天気予報JSONをもとに天気予報メールを送信する関数を作成

次に、getWeatherHacksJson関数から取得してきた天気予報JSONをもとに、天気予報メールを送信する関数を作ります。

<?php
// メールが文字化けしないように内部文字エンコーディングの設定をしておきましょう。
mb_language("Japanese");
mb_internal_encoding("UTF-8"); 

$wh = new WeatherHacksMail();
$wh->sendMail(450010, "配信先メールアドレス", "配信元メールアドレス");

class WeatherHacksMail{
    // ソース1の内容
    public function getWeatherHacksJson($city_id) {...}

    // 天気予報メール送信関数
    public function sendMail($city_id, $to, $from){
        $result = false;
        if(false !== $json = $this->getWeatherHacksJson($city_id)){
            $subject = $json->title;
            $header = "From:".mb_encode_mimeheader(mb_convert_encoding("天気予報","UTF-8","auto"))."<{$from}>";
            $body = date("m月d日の天気予報",strtotime($json->publicTime)) . "\r\n"
                . $json->link . "\r\n\r\n"
                . $json->description->text;

            // メールを送信する(成功した場合にTRUEを、失敗した場合にFALSEを返します。)
            $result = mb_send_mail($to, $subject, $body, $header);
        }
        return $result;
    }
}

sendMail関数へ地域ID,配信先メールアドレス,配信元メールアドレスを渡してあげると、配信先メールアドレスへ指定した地域の天気予報メールを送信してくれます。

$body変数に取得してきた天気予報JSONの内容を入れてあげてください。
今回天気予報メールで使用した情報は以下のプロパティのみ。

プロパティ 説明
link リクエストされたデータの地域に該当するlivedoor 天気予報のURL。
description->text 天気概況文。
description->publicTime 天気概況文の発表時刻。

実行すると僕宛にこんなメールが届きます。

f:id:kai_seiya:20150423231157p:plain

天気予報メールが届いた!完成!
やったぜ。これで傘を忘れずに済む!
ん…?でもなんか物足りない気がする。。。

そうだ、毎朝お天気お姉さんからメールが届いたらドキドキしちゃうかもしれない…!?

お天気お姉さん関数(仮)を作成

replaceGobi関数という、文章の語尾を置き換える関数を作ってみました。
"本文の内容"と"なりきりモード"を引数に渡すと、本文の内容が各なりきりモードの語尾に置き換えられて返ってきます。

今までのソースコード+お天気お姉さん関数(仮)のソースコードをマージしておきます。コピペして実行してみてください。

<?php
mb_language("Japanese");
mb_internal_encoding("UTF-8");

$wh = new WeatherHacksMail();
$wh->sendMail(450010, "配信先メールアドレス", "配信元メールアドレス", 2);

class WeatherHacksMail{
    /**
     * 天気予報のメールを送信する。
     *
     * @param integer $city_id 地域ID
     * @param string $to 送信先
     * @param string $from 送信元
     * @param integer $mode なりきりモード
     * @return boolean $result
     *   送信成功の場合はTRUEを返す。
     *   送信失敗もしくはJSONを取得できない場合はFALSEを返す。
     */
    public function sendMail($city_id, $to, $from, $mode = 0){
        $result = false;
        if(false !== $json = $this->getWeatherHacksJson($city_id)){

            $subject = $json->title;
            $header = "From:".mb_encode_mimeheader(mb_convert_encoding("天気予報","UTF-8","auto"))."<{$from}>";
            $body = date("m月d日の天気予報",strtotime($json->publicTime)) . "\r\n"
                . $json->link . "\r\n\r\n"
                . $json->description->text;

            if(is_numeric($mode) && $mode > 0){
                $body = $this->replaceGobi($body, $mode);
            }

            // メールを送信する(成功した場合にTRUEを、失敗した場合にFALSEを返します。)
            $result = mb_send_mail($to, $subject, $body, $header);
        }
        return $result;
    }

    /**
     * 天気予報のメールを送信する。
     *
     * @param integer $city_id 地域ID
     * @return mixed 天気予報の情報をJSONで返す。取得できない場合はFALSEを返す。
     */
    public function getWeatherHacksJson($city_id) {
        $url = "http://weather.livedoor.com/forecast/webservice/json/v1?city={$city_id}";
        if (false === $data = @file_get_contents($url)) {
            return false;
        }
        return json_decode($data);
    }

    /**
     * お天気お姉さん関数(仮) 本文の語尾が変わります。
     *
     * @param string $str 変換する文字列
     * @param integer $mode なりきりモード
     * @return string $str 変換した文字列
     */
    private function replaceGobi($str, $mode){
        switch($mode){
            case 1:
                $str = str_replace("ます。", "…ますわ。", $str);
                $str = str_replace("です。", "ですわ、たぶん…。", $str);
                $str = str_replace("でしょう。", "…ですわ、うん。", $str);
                break;
            case 2:
                $str = str_replace("ます。", "ますわ!", $str);
                $str = str_replace("です。", "ですわ!", $str);
                $str = str_replace("でしょう。", "よ!", $str);
                break;
        }
        return $str;
    }
}

実行してみると…。

f:id:kai_seiya:20150423231218p:plain

お天気お姉さんからメールが届いたですわ…!!!テンションMAXですわ↑
語尾の置換は好きなようにカスタマイズして朝のモチベーションを上げていきましょう↑↑

毎朝届くようにcronの設定をする

毎朝届かないと意味が無いのでcronで定期的に実行させてメールを送信するようにしましょう。
適当な非公開ディレクトリにPHPファイルを設置して、毎朝メールが届くようcronを設定して完了!

$ crontab -e
30 6 * * * cd 設置ディレクトリ ; php tenki.php

まとめ

どうでしたでしょうか?
これで毎朝傘を持って行こうか悩むことは無くなり、毎朝お天気お姉さんからメールが届く楽しみが増えたのではないでしょうか?

今回は1日1回取得しにいくだけなのでキャッシュについて触れませんでしたが、頻繁にリクエストするのであればキャッシュの考慮した方がいいかもですね。

みなさんもWeather Hacksを使ってみてください!
お天気お姉さんはきっと可愛い。