第28回 天気予報情報をWebから取得して解析する

今回は、天気予報と鉄道運用状況のデータをWebから取得して、解析するプログラムを試作してみます。

今回の説明内容

今回は、Webサイトから天気予報の情報と鉄道運用状況の情報を取得して、解析してみます。ちょっと長くなりそうなので、今回は天気予報データの取得と、LED点滅パターンを決定するための解析方法の検討をしてみます。鉄道運行情報の取得と解析は次回検討します。

今回の説明内容は以下になります。

  • 天気予報情報の取得
  • 天気予報データ解析の方針
  • PHPで天気予報文字列解析プログラムを作成
  • Pythonで天気予報文字列解析プログラムを作成
  • 補足

 

天気予報情報の取得

天気予報のデータを提供しているサイトは海外も含めて数多くあるようです。その中でも今回は「Weather Hacks」というサイトを利用してみたいと思います。このサイトにアクセスすると、指定した地域の、今日、明日、明後日の天気予報データを取得することができます。

ただし利用条件もあります。一つは、データの利用は個人的な範囲のみで商用利用は不可となっています。もう一つは、このサイトから取得したデータを表示するウェブページには、Livedoor天気情報へのリンクと著作権表示が推奨されています。どちらも特に問題ありませんので、このサイトを利用させていただく、ということにします。

それでは早速データ取得してみます。取得方法は簡単です。最初に天気予報データを取得したい地域コードを以下のページで調べます。

全国の地点定義表

私の住んでいる神奈川県東部は横浜が定義されていて、以下のように定義されています。

<city title="横浜" id="140010" source="http://weather.livedoor.com/forecast/rss/area/140010.xml"/>

このidが地域コードになります。横浜は 140010 です。

次にこのコードを以下の文字列の最後につけてWebページのリクエストをすると、天気予報の情報が返ってきます。

http://weather.livedoor.com/forecast/webservice/json/v1?city=

横浜であれば、

http://weather.livedoor.com/forecast/webservice/json/v1?city=140010

という文字列になります。具体的に取得してみます。ブラウザでこのURLにアクセスすると、、、

Json data

こんな感じで表示されます。内容の確認が難しいですが、これは文字コードがエスケープされたUTF-8のコードのためです(UTF-8をACSII文字のみで構成したもの)。プログラムでは問題なく扱えます。

なお、このデータ形式はjsonになっています。JavaScript Object Notationの略なんですが、細かい説明は省略して使い方を確認しておきます。jsonのデータは非常に簡単な構成で、前回出てきましたPHPの連想配列、Pythonの辞書に似ています。jsonはキーと値から構成されていて、フォーマットは以下のようになっています。

{ キー : 値 , キー : 値 , ... }

例えば以前出てきた商品の値段では、

{
    "apple_fuji" : 138,
    "unshu_mikan" : 398
}

という感じです。また配列も定義できて、カンマ区切りのデータを [ ] で囲みます。これだけわかれば、先ほどの取得したデータは読めると思います。ただ、エスケープされたUTF-8文字は人間が読むにはなかなかむずかしいものがありますので、以下のページの下の方に取得データのサンプルがあるので確認してみてください。

お天気Webサービス仕様

この取得したデータをプログラムで扱うのも簡単です。PHPやPythonではjsonデータを連想配列や辞書に入れてくれる関数がありますので、前回出てきました連想配列や辞書と同じアクセス方法になります。

それでは、サンプルプログラムで確認してみます。取得したデータから地域名と今日の天気予報を表示するプログラムを作ってみます。

地域名は、jsonデータの “title”キーに、今日の天気予報は、”forecasts”キーの最初の配列要素の”telop”キーに入っています。

あとは特に新しい知識なしでわかると思います。以下がPHPのプログラムです。”get_weather.php”というファイル名で作成しました。

#!/usr/bin/php

<?php

// 天気取得のURL設定
// $cityに地域コードを設定
$city = "140010";  // 横浜
// 取得URLを生成
$url = "http://weather.livedoor.com/forecast/webservice/json/v1?city=$city";

// 天気データ取得
// 最初に指定URLのデータを取得
$response = file_get_contents($url);
// jsonデータのためjson_decode関数で連想配列に変換
$weather = json_decode($response,true);

// 取得したデータを表示
// jsonデータのtitleと、forecastsの最初の要素のtelopを表示
echo $weather["title"] . " : " . $weather["forecasts"][0]["telop"];

?>

指定したURLのレスポンスをもらうには、file_get_contents()関数を使用します。この関数で先ほどブラウザで確認したデータが$responseに格納されますので、そのデータをjson_decode()関数で連想配列に変換します。

このファイルに実行権をつけて(chmod +x get_weather.php、覚えてますか?)、実行してみます。

pi@raspberrypi ~/dev $ ./get_weather.php

神奈川県 横浜 の天気 : 晴時々曇

このように表示されればOKです。

Pythonのプログラムは以下になります。

#!/usr/bin/python
# coding: utf-8

# モジュールインポート
import json, urllib2

# 天気取得のURL設定
# cityに地域コードを設定
city = "140010"
# 取得URLを生成
url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=%s' % city

try:
    # 天気データ取得
    # 最初に指定URLのデータ取得
    response = urllib2.urlopen(url)
    # jsonデータ取得
    weather = json.loads(response.read())

    # 取得したデータを表示
    # titleとforecastsの最初の要素のtelopを表示
    print weather['title'] + " : " + weather['forecasts'][0]['telop']

finally:
    response.close()

指定URLのデータ取得にurllib2というモジュール、jsonデータ解析にjsonというモジュールを使用しています。なお、11行目のURLを生成するところですが、PHPの場合は文字列の中の変数を展開する形でしたが、Pythonの場合は、C言語のprintfのように、一度表示する文字列内でフォーマットを指定をして( ‘….%s”)、その後に%に続いてそこに流し込む変数を書きます。

他は特に難しいところはないと思いますが、不明点がありましたら問い合わせフォームかコメント欄でご質問ください。

これで天気予報データの取得が確認できました。

 

天気予報データ解析の方針

先ほどのサンプルプログラムで取得した天気予報は「晴時々曇」でした。天気予報からLEDの点滅パターンにどうやって変換していけばよいのか、これから考えてみます。

どうやって解析すればよいか、いろいろ方法はあると思いますが、逆算で考えていきたいと思います。前回の記事で、LEDの点滅制御を行うために、基本パターン(on, off, blink)を組み合わせて各LEDの点滅パターンを生成、それを元に点滅制御を行いました。

天気予報データに基づいてLEDの点滅制御を行うために、各LEDがどのような組み合わせの基本パターンか決定できれば、前回のやり方でLEDを点滅制御できます。ということで具体例を元に考えてみます。

例えば、先ほどの「晴時々曇り」であれば、晴れのLEDの点滅パターンは、「点灯」「消灯」「消灯」、曇りのLEDの点滅パターンは「消灯」「点滅」「消灯」になります。ということは、最終的には、各LEDの基本点滅パターンの入った連想配列(PHP)あるいは辞書(Python)に変換しておけば、あとはなんとかなると思います。

イメージとしてはこんな感じです。例としては「晴時々曇り」で、PHPの連想配列のケースです。

$weather_pat = {
"fine" => ["on", "off", "off"],
"cloud" => ["off", "blink", "off"],
"rain" => ["off", "off", "off"],
"snow" => ["off", "off", "off"],
};

次に「晴時々曇り」という文字列から、どうやってこのパターンに変換するか考えてみます。まず晴れについて考えてみます。結果として、晴れのLEDパターンが “on” + “off” + “off” に決定できればいいわけです。予報の文字列の中に「晴」が含まれていたら “on” + “off” + “off” にする、というのはダメです。というのは、単なる「晴れ」という予報の時は晴れのLEDはつけたままになります。つまり以下の予報の時の晴れのLED点滅パターンは

「晴れ」→ “on” + “on” + “on”
「晴時々曇り」→ “on” + “off” + “off”

となります。ということは、予報に「晴」の文字があっても、これだけではLEDの点滅パターンは決定できません。上の2つの例を見ると、判定の仕方としては、

  1. 最初に予報の文字が「晴れ」に完全一致したら、晴れのLEDのパターンは “on” + “on” + “on” に決定
  2. そうでない場合、予報文字の最初に「晴」の文字があれば、”on” + “off” + “off”に決定

という方法はどうでしょうか。となると「曇時々晴」とかいう場合はどうすればいいのか。。。

ということで、どんな予報文字列があるのか確認してみます。と行きたいところですが、まとまった情報が見つかりませんでした。わかる範囲で調べたところ、以下の文字列があるようです。

晴れ主体の予報

曇り関連 雨関連 雪関連 その他
晴時々曇
晴のち曇
晴一時雨
晴のち雨
晴時々雨
晴一時雷雨
晴のち一時雨
晴のち雷雨
晴一時雪
晴のち雪
晴時々雪
晴のち一時雪
晴れ
晴一時雨か雪
晴一時雪か雨
晴時々雨か雪
晴時々雪か雨
晴のち雨か雪
晴のち雪か雨

曇り主体の予報

晴れ関連 雨関連 雪関連 その他
曇時々晴
曇のち晴
曇一時雨
曇時々雨
曇のち雨
曇一時雷雨
曇時々雨雷
曇のち一時雨
曇一時雪
曇時々雪
曇時々雪雷
曇のち一時雪
曇のち雪
曇り
曇一時雨か雪
曇一時雪か雨
曇時々雨か雪
曇時々雪か雨
曇のち雨か雪
曇のち雪か雨
曇のち雨か雷雨

雨主体の予報

晴れ関連 曇り関連 雪関連 その他
雨時々晴
雨のち晴
雨時々曇
雨のち曇
雨一時雪
雨か雪
雨のち雪

雷雨
雨か雪のち晴
雨か雪のち曇
大雨
暴風雨

雪主体の予報

晴れ関連 曇り関連 雨関連 その他
雪時々晴
雪のち晴
雪時々曇
雪のち曇
雪一時雨
雪か雨
雪のち雨

雷雪
雪か雨のち晴
雪か雨のち曇
大雪
暴風雪

、、、、、、、、、

なんで予報ってこんなにあるんですかね(怒)。なんて言っても状況は変わりませんので、引き続き解析の方針を検討します。

先ほどのように、晴れのLEDパターンを決定する方法として、「晴れ」に完全一致していれば”on” + “on” + “on”、「晴」の文字が先頭にあれば、”on” + “off” + “off”というルールでいけそうです。晴れのLEDについては、「時々晴」という文字があれば、”off” + “blink” + “off”でOKそうです。「のち晴」の場合は、”off” + “on” + “off”でいけますよね。

ということで、ここまでの予報文字列の判定方法をまとめてみます。

LED種類 判定 LED点滅パターン
晴れのLED 「晴れ」に完全一致 on + on + on
「のち晴」を含む off + on + off
「時々晴」を含む off + blink + off
曇りのLED 「曇り」に完全一致 on + on + on
「のち曇」を含む off + on + off
「時々曇」を含む off + blink + off
雨のLED 「雨」に完全一致 on + on + on
「のち雨」を含む off + on + off
「時々雨」を含む off + blink + off
雪のLED 「雪」に完全一致 on + on + on
「のち雪」を含む off + on + off
「時々雪」を含む off + blink + off

あとは例外を解決していきます。このルールで漏れるパターンは幾つかタイプがあります。

例えば「晴のち一時雨」は上のルールでは「晴一時雨」と判定されます。今回は、「晴のち一時雨」のようなパターン表現は検討していませんでしたので、このような場合は、「晴一時雨」に集約してしまいたいと思います。「晴時々雨か雪」も同様で、これは上のルールでは「晴時々雨」に判定されます。これもこのように集約してしまいます。(「雨か雪」などの表現もする場合についてはチャレンジ課題にしたいと思います)

このように集約されてしまってもOKな場合はよいでが、いずれの判定にも引っかからない予報文字列があります。

「晴のち雷雨」は、「晴」については判定されますが、「のち雷雨」は上のいずれのパターンにも引っかかりません。また、「大雨」「暴風雨」も上のパターンに引っかかりません。考えてみると、今回は雷は表現しませんし、「大雨」や「暴風雨」も表現しませんので、これらはいずれも「雨」になります。(雷についてはチャレンジ課題にしたいと思います)

これは、上のパターン判別をする前に、予報文字列から「雷」「大」「暴風」を削除する処理を入れたいと思います。

ただ、これでもうまく判別できない予報文字列があります。「雨か雪」と「雪か雨」です。上の判定パターンの場合「雨か雪」は雨のLEDのみ on + off + offになります。「雨か雪」を「雨」にしてしまうのであれば、雨のLEDは点灯したまま、on + on + on のパターンにしたほうが良いです。これを解決するために、完全一致パターンとして、「雨か雪」と「雪か雨」はそれぞれ「雨」と「雪」に変換しておきます。

これでおそらく一通りの予報文字列が、今回表現するパターンに対応できると思います。あまり細かく分けると、連想配列や辞書を使った対応表形式にしてしまったほうが早いと思いますのでこのぐらいにしておきたいと思います。

このパターンの判定アルゴリズムと、全てのパターンの検証をするサンプルプログラムを作成してみます。最初に全ての予報文字列を用意して、それを判定させてみます。

 

PHPで天気予報文字列解析プログラムを作成

それでは早速PHPでプログラムを作成してみます。解析方法は上に説明した通りですので、その流れに沿ってプログラムを作成してみました。プログラムの後に、必要と思われる箇所の説明をします。

#!/usr/bin/php

<?php

// 天気予報文字列定義
$weather = [
    "晴れ",
    "晴時々曇",
    "晴一時雨",
    "晴時々雨",
    "晴一時雪",
    "晴時々雪",
    "晴一時雷雨",
    "晴時々雷雨",
    "晴一時雨か雪",
    "晴一時雪か雨",
    "晴時々雨か雪",
    "晴時々雪か雨",
    "晴のち曇",
    "晴のち一時雨",
    "晴のち雨",
    "晴のち一時雪",
    "晴のち雪",
    "晴のち雨か雪",
    "晴のち雪か雨",
    "晴のち雷雨",
    "曇り",
    "曇時々晴",
    "曇一時雨",
    "曇時々雨",
    "曇一時雪",
    "曇時々雪",
    "曇一時雷雨",
    "曇時々雨雷",
    "曇時々雪雷",
    "曇一時雨か雪",
    "曇一時雪か雨",
    "曇時々雨か雪",
    "曇時々雪か雨",
    "曇のち晴",
    "曇のち一時雨",
    "曇のち雨",
    "曇のち一時雪",
    "曇のち雪",
    "曇のち雨か雪",
    "曇のち雪か雨",
    "曇のち雨か雷雨",
    "雨",
    "雨時々晴",
    "雨時々曇",
    "雨一時雪",
    "雨か雪",
    "雷雨",
    "雨のち晴",
    "雨のち曇",
    "雨のち雪",
    "雨か雪のち晴",
    "雨か雪のち曇",
    "大雨",
    "暴風雨",
    "雪",
    "雪時々晴",
    "雪時々曇",
    "雪一時雨",
    "雪か雨",
    "雷雪",
    "雪のち晴",
    "雪のち曇",
    "雪のち雨",
    "雪か雨のち晴",
    "雪か雨のち曇",
    "大雪",
    "暴風雪",
];

// LED点滅パターン配列
$led_pat = [];

// 天気予報文字列の解析
foreach( $weather as $string ) {

    // 解析対象外の文字を削除
    $string = str_replace(["大", "暴風", "雷"], "", $string);

    // 「一時」を「時々」に置換
    $string = str_replace("一時", "時々", $string);

    // 「雨か雪」と「雪か雨」をそれぞれ「雨」と「雪」に変換
    $string = str_replace("雨か雪", "雨", $string);
    $string = str_replace("雪か雨", "雪", $string);

    // 晴れの解析
    // 最初に「晴」の完全一致を確認
    if( strcmp($string, "晴れ") == 0 ) {
        // 「晴れ」に完全一致していれば、晴のLEDは点灯したまま
        $led_pat += [ "fine" => ["on", "on", "on"] ]; 
    } else {
        // 「晴れ」に完全一致していなければ、「晴」の文字が含まれているか確認
        $pos = strpos($string, "晴");
        if ( $pos !== false ) {
            // 「晴」の文字が含まれている場合の処理
            if ( $pos == 0 ) {
                // 先頭に「晴」がある場合
                $led_pat += [ "fine" => ["on", "off", "off"] ];
            } else {
                // 先頭にない場合は「時々晴」と「のち晴」を確認
                if ( strpos($string, "時々晴") !== false ){
                    $led_pat += [ "fine" => ["off", "blink", "off"] ];
                } else {
                    if ( strpos($string, "のち晴") !== false ){
                        $led_pat += [ "fine" => ["off", "on", "off"] ];
                    } else {
                        // いずれでもない場合は消灯にする
                        $led_pat += [ "fine" => ["off", "off", "off"] ];  
                    }
                }
            }
        } else {
            // 予報文字列に晴れはないのでLEDは消灯したまま
            $led_pat += [ "fine" => ["off", "off", "off"] ];
        }
    }

    // 曇りの解析
    if( strcmp($string, "曇り") == 0 ) {
        $led_pat += [ "cloud" => ["on", "on", "on"] ]; 
    } else {
        $pos = strpos($string, "曇");
        if ( $pos !== false ) {
            if ( $pos == 0 ) {
                $led_pat += [ "cloud" => ["on", "off", "off"] ];
            } else {
                if ( strpos($string, "時々曇") !== false ) {
                    $led_pat += [ "cloud" => ["off", "blink", "off"] ];
                } else {
                    if ( strpos($string, "のち曇") !== false ) {
                        $led_pat += [ "cloud" => ["off", "on", "off"] ];
                    } else {
                        // いずれでもない場合は消灯にする
                        $led_pat += [ "cloud" => ["off", "off", "off"] ];  
                    }
                }
            }
        } else {
            $led_pat += [ "cloud" => ["off", "off", "off"] ];
        }
    }

    // 雨の解析
    if( strcmp($string, "雨") == 0 ) {
        $led_pat += [ "rain" => ["on", "on", "on"] ]; 
    } else {
        $pos = strpos($string, "雨");
        if ( $pos !== false ) {
            if ( $pos == 0 ) {
                $led_pat += [ "rain" => ["on", "off", "off"] ];
            } else {
                if ( strpos($string, "時々雨") !== false ) {
                    $led_pat += [ "rain" => ["off", "blink", "off"] ];
                } else {
                    if ( strpos($string, "のち雨") !== false ) {
                        $led_pat += [ "rain" => ["off", "on", "off"] ];
                    } else {  
                        // いずれでもない場合は消灯にする
                        $led_pat += [ "rain" => ["off", "off", "off"] ];  
                    }
                }
            }
        } else {
            $led_pat += [ "rain" => ["off", "off", "off"] ];
        }
    }

    // 雪の解析
    if( strcmp($string, "雪") == 0 ) {
        $led_pat += [ "snow" => ["on", "on", "on"] ]; 
    } else {
        $pos = strpos($string, "雪");
        if ( $pos !== false ) {
            if ( $pos == 0 ) {
                $led_pat += [ "snow" => ["on", "off", "off"] ];
            } else {
                if ( strpos($string, "時々雪") !== false ) {
                    $led_pat += [ "snow" => ["off", "blink", "off"] ];
                } else {
                    if ( strpos($string, "のち雪") !== false ) {
                        $led_pat += [ "snow" => ["off", "on", "off"] ];
                    } else {  
                        // いずれでもない場合は消灯にする
                        $led_pat += [ "snow" => ["off", "off", "off"] ];  
                    }
                }
            }
        } else {
            $led_pat += [ "snow" => ["off", "off", "off"] ];
        }
    }

    // 変換後の予報文字列を表示して、
    // それに対応するLED点滅パターンを表示
    echo "----------\n";
    echo $string . "\n";
    foreach( $led_pat as $key => $value ) {
        echo $key . ": ";
        foreach( $value as $pat) {
            echo $pat . " ";
        }
        echo "\n";
    }

    // $led_patを初期化
    $led_pat = [];
}

?>

82行目〜90行目

解析対象外の文字の削除、置換を行っています。str_replace()という関数を使用します。str_replace(置換対象文字列, 置換文字列, 置換対象);という引数になります。例えば、$stringの文字列中、「暴風」削除したい場合、「暴風」を空の文字 “” で置き換えるように

str_replace("暴風", "", $string);

と書きます。なお置換対象文字列は配列でもOKです。

99行目

文字列が先頭にあるか、文字列が含まれているか、というのは strpos()関数を使用します。この関数は、検索文字が検索対象文字列の何文字目にあるか調べます。例えば以下のようになります。

$string = "abcdefg";

とした場合、

echo strpos($string, "c");

を実行すると 2 となります。aが0番目となりますので、cは2番目という意味です。なお、日本語などのマルチバイトの場合は、マルチバイト単位でカウントした値ではないため注意が必要です。

また、文字が見つからなかった場合は false が返り値となります。PHPの場合、0とfalseは別物なので特にif文などで注意が必要です。C言語では、if文などでは0とfalseは同じ意味で扱えますが、PHPの場合、if文での判定は一致確認の場合は「===」、不一致確認の場合は「!==」を使います。100行目でその判定をしていますので、参考にしてみてください。

 

Pythonで天気予報文字列解析プログラムを作成

以下はPythonのプログラムです。プログラムのあとに、必要と思われる行に説明をしています。

#!/usr/bin/python
# coding: utf-8

# 天気予報文字列定義
weather = (
    '晴れ',
    '晴時々曇',
    '晴一時雨',
    '晴時々雨',
    '晴一時雪',
    '晴時々雪',
    '晴一時雷雨',
    '晴時々雷雨',
    '晴一時雨か雪',
    '晴一時雪か雨',
    '晴時々雨か雪',
    '晴時々雪か雨',
    '晴のち曇',
    '晴のち一時雨',
    '晴のち雨',
    '晴のち一時雪',
    '晴のち雪',
    '晴のち雨か雪',
    '晴のち雪か雨',
    '晴のち雷雨',
    '曇り',
    '曇時々晴',
    '曇一時雨',
    '曇時々雨',
    '曇一時雪',
    '曇時々雪',
    '曇一時雷雨',
    '曇時々雨雷',
    '曇時々雪雷',
    '曇一時雨か雪',
    '曇一時雪か雨',
    '曇時々雨か雪',
    '曇時々雪か雨',
    '曇のち晴',
    '曇のち一時雨',
    '曇のち雨',
    '曇のち一時雪',
    '曇のち雪',
    '曇のち雨か雪',
    '曇のち雪か雨',
    '曇のち雨か雷雨',
    '雨',
    '雨時々晴',
    '雨時々曇',
    '雨一時雪',
    '雨か雪',
    '雷雨',
    '雨のち晴',
    '雨のち曇',
    '雨のち雪',
    '雨か雪のち晴',
    '雨か雪のち曇',
    '大雨',
    '暴風雨',
    '雪',
    '雪時々晴',
    '雪時々曇',
    '雪一時雨',
    '雪か雨',
    '雷雪',
    '雪のち晴',
    '雪のち曇',
    '雪のち雨',
    '雪か雨のち晴',
    '雪か雨のち曇',
    '大雪',
)

# LED点滅パターン辞書の初期化
ledPat = {}

# 天気予報文字列の解析
for weatherStr in weather:

    # 解析対象外の文字を削除
    weatherStr = weatherStr.replace('大', '').replace('暴風', '').replace('雷', '')

    # 「一時」を「時々」に置換
    weatherStr = weatherStr.replace('一時', '時々')

    # 「雨か雪」と「雪か雨」をそれぞれ「雨」と「雪」に置換
    weatherStr = weatherStr.replace('雨か雪', '雨')
    weatherStr = weatherStr.replace('雪か雨', '雪')

    # 晴れの解析
    # 最初に「晴れ」の完全一致を確認
    if weatherStr == '晴れ':
        # 「晴れ」に完全一致していれば、晴れのLEDは点灯したままのパターン
        ledPat.update({'fine': ('on', 'on', 'on')})
    else:
        # 「晴」の文字が含まれているか確認
        pos = weatherStr.find('晴')
        if pos >= 0:
            # 「晴」が含まれている場合
            if pos == 0:
                # 先頭に「晴」がある場合
                ledPat.update({'fine': ('on', 'off', 'off')})
            else:
                # 先頭に「晴」がない場合は「時々晴」と「のち晴」を確認
                if weatherStr.find('時々晴') > 0:
                    ledPat.update({'fine': ('off', 'blink', 'off')})
                else:
                    if weatherStr.find('のち晴') > 0:
                        ledPat.update({'fine': ('off', 'on', 'off')})
                    else:
                        # いずれでもない場合は消灯する
                        ledPat.update({'fine': ('off', 'off', 'off')})
        else:
            # 予報文字列に「晴」はないのでLEDは消灯
            ledPat.update({'fine': ('off', 'off', 'off')})

    # 曇りの解析
    if weatherStr == '曇り':
        ledPat.update({'cloud': ('on', 'on', 'on')})
    else:
        pos = weatherStr.find('曇')
        if pos >= 0:
            if pos == 0:
                ledPat.update({'cloud': ('on', 'off', 'off')})
            else:
                if weatherStr.find('時々曇') > 0:
                    ledPat.update({'cloud': ('off', 'blink', 'off')})
                else:
                    if weatherStr.find('のち曇') > 0:
                        ledPat.update({'cloud': ('off', 'on', 'off')})
                    else:
                        ledPat.update({'cloud': ('off', 'off', 'off')})
        else:
            ledPat.update({'cloud': ('off', 'off', 'off')})

    # 雨の解析
    if weatherStr == '雨':
        ledPat.update({'rain': ('on', 'on', 'on')})
    else:
        pos = weatherStr.find('雨')
        if pos >= 0:
            if pos == 0:
                ledPat.update({'rain': ('on', 'off', 'off')})
            else:
                if weatherStr.find('時々雨') > 0:
                    ledPat.update({'rain': ('off', 'blink', 'off')})
                else:
                    if weatherStr.find('のち雨') > 0:
                        ledPat.update({'rain': ('off', 'on', 'off')})
                    else:
                        ledPat.update({'rain': ('off', 'off', 'off')})
        else:
            ledPat.update({'rain': ('off', 'off', 'off')})


    # 雪の解析
    if weatherStr == '雪':
        ledPat.update({'snow': ('on', 'on', 'on')})
    else:
        pos = weatherStr.find('雪')
        if pos >= 0:
            if pos == 0:
                ledPat.update({'snow': ('on', 'off', 'off')})
            else:
                if weatherStr.find('時々雪') > 0:
                    ledPat.update({'snow': ('off', 'blink', 'off')})
                else:
                    if weatherStr.find('のち雪') > 0:
                        ledPat.update({'snow': ('off', 'on', 'off')})
                    else:
                        ledPat.update({'snow': ('off', 'off', 'off')})
        else:
            # 予報文字列に「晴」はないのでLEDは消灯
            ledPat.update({'snow': ('off', 'off', 'off')})

    print '---------'
    print weatherStr
    print ledPat

    ledPat = {}

75行目

各LEDの点滅パターンはledPatという名前の辞書に格納することにします。

78行目

for 〜 in 〜 文で、weatherリストに入っている天気予報文字列を一つずつ取り出して解析をします。

81行目

大雨、暴風雪、雷などの今回のパターンで表現しない文字はここで削除します。replace()関数は引数が2つあり、raplace(検索文字列, 置換文字列)と書くと、検索文字列を検索して、見つかったら置換文字列に置き換えます。検索対象文字列の全てに対して検索・置換を行います。

97行目

先ほどはreplace()関数で文字を置換しましたが、今回は検索するだけです、find()関数は引数の文字あるいは文字列を検索して、何文字目に見つかったかを返します。最初も文字は0文字目、見つからなかったら-1を返します。

 

補足

プログラムを見ると、各天気の解析が同じコードになっていますよね。これは関数にしたほうがすっきりしますので、最後にプログラムをまとめる時に関数にするか、チャレンジ課題にしようと思います。

« »