2012年3月19日月曜日

Mac, Geektool, Weather Forecast, PHP, Google Unofficial API, Japanese

今日もGeektoolのこと.天気予報を日本語で表示しようという話.
↓こんな感じになる.
Gmailガジェットが見切れているのは気にしてはいけない.
Macを少し触って,素晴らしいなと思ったのは,PerlもawkもPHPもインストール済みだということ.コマンドラインでガリガリいじれるってのは楽だ.
さて,今日の肝はPHPでXMLをいじるということ.非常に簡単にXMLをオブジェクト化できる.ただし,文字コードがちゃんとしれいればだけれども.これで2日ハマった.とりあえず,非公式のAPIとはいえ,xmlのヘッダーにcharsetを指定しないでSJISのXMLを返してくるgoogle様はどうかしているとしか思えない.


とりあえず,ここにスクリプトを置いておく.これ以外に用意するものは,天気アイコン.適当なものを見つけてきて,phpスクリプトを参考にして,ファイル名などを設定する.

設置方法は,Geektoolのshellでコマンド部分に
 php PATH/gw.php 【取得したい都市】
としてやると,テキスト部分が表示される.PATHはgw.phpを設置したところ.【取得したい都市】には,都市名をアルファベットで入れてやる.例えば仙台市だったら,sendai,miyagiとなる.多分,sendaiだけでも取得できる.この引数を指定しなければ,東京都の天気(代表地点がどこかは知らない)が表示される.以下,phpスクリプトの解説など.

 #!/usr/bin/php
<?php
    define("ICON_SOURCE_PATH","/hogeoge/");
hogehogeと打ったつもりが,2つ目のhを打ち損じた.めんどうなのでそのままになっている.ここには,天気アイコンフォルダのパスを入れる.例えば/Users/hoge/Document/geektool/Weather/icons/みたいな感じ.
    define("TEMP_PATH","/tmp/");
これはいじる必要ない.天気アイコンをコピーする場所.Geektoolの画像で指定するので覚えておくこと.
//適当な天気アイコンをダウンロードして,適宜書き換えること.
    define("ICON_EXTENTION", ".png");
//この配列変数も,利用する天気アイコンに合わせて適宜書き換える.
    $icon=array(
 (略)
 );
コメントに書いてあるように,利用するアイコンに合わせて設定してやる.今回のこれが,Google APIがXMLの中で指定しているアイコン画像をダウンロードするスクリプトだったら, こんな手間はかからないのだが,如何せん,Google様のアイコンがダサい.自分で好きな画像を見つけてきた方が満足度が高いので,こんな面倒臭いことになっている.あくまで,私が満足するためにやっていることなのだ.
//引数から対象地域を設定.引数がなければ,東京の天気を表示
if($argv[1]){
$city = $argv[1];
}else{
$city ='tokyo';
}
先述の通り.
    $url = 'http://www.google.com/ig/api?weather=' . $city . '&hl=ja';
    $content = mb_convert_encoding(file_get_contents($url),'UTF-8', 'Shift-JIS');
    $xml = simplexml_load_string($content);
    $weather=$xml->weather;
このスクリプトの肝はsimplexml_load_string.simplexml_load_file関数を使おうと思ったのだが,Google様の素晴らしい仕様のお陰さまですこのやろうsuck
取り乱しました.SJISだと,エラーが出て,オブジェクト化できない.なので,対象URLの内容をfile_get_contentsで文字列としてダウンロードして,mb_convert_encodingでUTF-8に変換し,simplexml_load_stringしている.
&hl=jpの部分で,日本語で表示するように指定している.これがなければ,英語表示として取得できる.ただし,先述の$iconでキーに指定しているファイル名が違ってくる.日本語表示の場合はjp_で始まるgif画像だが,英語表示ではjp_が付かないファイル名になるのかと思いきや,全く違うファイル名になる場合がある.もし英語表示で使う場合は,調整が必要となる.もっとも,英語表示でいいんだったら,わざわざこんな面倒くさいスクリプトを使わず,yahoo.comの天気予報を使えばいい.Geektoolでの利用法など,少しググれば解説サイトは簡単に見つかる.
    $info = $weather->forecast_information;
    $current = $weather->current_conditions;

    copy(ICON_SOURCE_PATH . $icon[basename($current->icon->attributes(),'.gif')] . ICON_EXTENTION, TEMP_PATH . "weather_current" . ICON_EXTENTION); // 現在の天気アイコンをコピー
現在の天気を示すアイコンはweather_current.png(拡張子部分は利用する天気アイコンで変わる)となる.
    $str = str_replace('-', '/', $info->forecast_date->attributes()) . "\n";//日付を整形
    $str.= "現在: " . $current->condition->attributes() . "\n";
    $str.= "気温: " . $current->temp_c->attributes();
//このほか,現在の天気情報には湿度,華氏気温もあるが,このスクリプトでは使わない.
    for($i=0; $i<count($weather->forecast_conditions); $i++){
        $forecast=$weather->forecast_conditions[$i];
        copy(ICON_SOURCE_PATH . $icon[basename($forecast->icon->attributes(),'.gif')] . ICON_EXTENTION, TEMP_PATH . "weather_forecast" . $i . ICON_EXTENTION); // 予報の天気アイコンをコピー
今日の今後の天気アイコンはweather_forecast0.png,明日の天気アイコンはweather_forecast1.png,あさっては(略)2.png・・・となる.
//整形しやすくするために,各値を変数に代入
        $low = $forecast->low->attributes();
        $high = $forecast->high->attributes();
        $condition = $forecast->condition->attributes();
//今日の予報と明日以降の予報で処理を分ける
        if($i==0){
            $day = "";
            $str.= "(" . $low . "-" . $high . "℃)\n";
            $str.= "予報: " . $condition;
        }else{
        $str.= "\n------------------\n"; //セパレーター
            $day = $forecast->day_of_week->attributes() . "曜日";
            $str.= $day . "\n" . $condition . "\n" . $low . "-" . $high . "℃";
        }

    }
    $str.= "\n";
    echo $str;
?>
こんな感じ.

0 件のコメント:

コメントを投稿