tech.guitarrapc.cóm

Technical updates

PowerShellでGlobalWeatherから天気情報取得してみる

開始しようとして某星人に早々に答え言われました ( めげずに見たところ、返ってきたデータがXMLだったのでJsonにはしてませんが一応できました。 もしPowerShellでJsonする場合は、以下が参考になります。
PowerShellでJScript.NETを利用してJSONをパースする

取得サイト

定番ですが、GlobalWeatherから取得しました。
GlobalWeather

コマンドレット

定番ですが、New-WebServiceProxyを使いました。
New-WebServiceProxy

国、都市の取得

天気はGetWeatherから取得出来るのですが、City,Coutryが必要とのこと。 まずは都市の一覧をGetCitiesByCountry取得します。
$web = New-WebServiceProxy -Uri http://www.webservicex.net/globalweather.asmx
$web.GetCitiesByCountry("Japan") `
    | %{([xml]$_).NewDataSet.Table} `
    | sort City

Function化

流用したいので、以下のfunctionに書き直してっと。 ※恐らく日本人が見るでしょうから、デフォルト値をJapanにしています。
function Get-CityCountry{

    [CmdletBinding()]
    param(
    #引数がなかった場合はJapanを指定
    [parameter (Position=0,ValueFromPipeline=$true)]
    [string]$Country="Japan"
    )

    begin{
        $web = New-WebServiceProxy -Uri http://www.webservicex.net/globalweather.asmx
    }

    process{

        $web.GetCitiesByCountry($Country) `
            | %{([xml]$_).NewDataSet.Table} `
            | sort City
    }

}
これで、以下の一文でその国の都市一覧が取得できます。
Get-CityCountry -Country Japan
アメリカを取得するなら以下です。
Get-CityCountry -Country "United States"
イギリスを取得するなら以下です。
Get-CityCountry -Country "United Kingdom"

取得結果例

Japanの取得結果です。
Country City
------- ----
Japan   Akeno Ab
Japan   Akita Airport
Japan   Amami Airport
Japan   Aomori Airport
Japan   Asahikawa Ab
Japan   Asahikawa Airport
Japan   Ashiya Ab
Japan   Atsugi United States Naval Air Station
Japan   Chichijima
Japan   Chitose Ab
Japan   Chitose Japanese Air Self Defense Force
Japan   Chofu Airport
Japan   Fuji Ab
Japan   Fukue Airport
Japan   Fukui Airport
Japan   Fukuoka Airport
Japan   Fukushima Airport
Japan   Futenma Marine Corps Air Facilit
Japan   Gifu Ab
Japan   Hachijojima Airport
Japan   Hachinohe Ab
Japan   Hakodate Airport
Japan   Hamamatsu Ab
Japan   Hamby U. S. Army Airfield
Japan   Hanamaki Airport
Japan   Hiroshima Airport
Japan   Hofu Ab
Japan   Hyakuri Ab
Japan   Ichikawa
Japan   Iejima Auxiliary Ab
Japan   Iki Airport
Japan   Iruma Ab
Japan   Ishigakijima
Japan   Iwakuni Marine Corps Air Station
Japan   Iwami Airport
Japan   Iwojima
Japan   Izumo Airport
Japan   Kadena Ab
Japan   Kagoshima Airport
Japan   Kamigoto
Japan   Kanoya Ab
Japan   Kansai International Airport
Japan   Kasumigaura Ab
Japan   Kasuminome Ab
Japan   Kikai Island
Japan   Kisarazu Ab
Japan   Kitakyushu Airport
Japan   Kochi Airport
Japan   Komatsu Ab
Japan   Komatsujima Ab
Japan   Kumamoto Airport
Japan   Kumejima
Japan   Kushiro
Japan   Kushiro Airport
Japan   Matsumoto Airport
Japan   Matsushima Ab
Japan   Matsuyama Airport
Japan   Memambetsu Airport
Japan   Metabaru Ab
Japan   Miho Ab
Japan   Minamidaitojima
Japan   Minamitorishima
Japan   Misawa Ab
Japan   Miyakejima Airport
Japan   Miyakojima
Japan   Miyazaki Airport
Japan   Mombetsu Airport
Japan   Muroran
Japan   Nagasaki Airport
Japan   Nagoya Airport
Japan   Naha Airport
Japan   Nakashibetsu Airport
Japan   Nankishirahama Airport
Japan   New Tokyo Inter-National Airport
Japan   Niigata Airport
Japan   Nyutabaru Ab
Japan   Obihiro Airport
Japan   Oita Airport
Japan   Ojika Island
Japan   Okayama Airport
Japan   Oki Airport
Japan   Okinoerabu
Japan   Okushiri Island
Japan   Ominato Ab
Japan   Osaka International Airport
Japan   Oshima Airport
Japan   Ozuki Ab
Japan   Rebun Island
Japan   Rishiri Island
Japan   Sado Airport
Japan   Sapporo Ab
Japan   Sasebo Usn
Japan   Sendai Airport
Japan   Shimofusa Ab
Japan   Shizuhama Ab
Japan   Tachikawa Ab
Japan   Tajima
Japan   Takamatsu Airport
Japan   Tanegashima Airport
Japan   Tateyama Ab
Japan   Tokachi Japanese Ground Self Defense Force
Japan   Tokunoshima Island
Japan   Tokushima Ab
Japan   Tokyo
Japan   Tokyo Heliport
Japan   Tokyo International Airport
Japan   Tottori Airport
Japan   Toyama Airport
Japan   Tsuiki Ab
Japan   Tsushima Airport
Japan   Utsunomiya Ab
Japan   Wakkanai Airport
Japan   Yakushima
Japan   Yamagata Airport
Japan   Yamaguchi Ube Airport
Japan   Yao Airport
Japan   Yokosuka Fwf
Japan   Yokota Ab
Japan   Yonaguni Airport
Japan   Zama Airfield

天気の取得

ここまで来れば簡単で、GetWeatherから天気を取得してみます。
$web = New-WebServiceProxy -uri http://www.webservicex.net/globalweather.asmx
[xml]$xml = $web.GetWeather("Tokyo","Japan")
$xml.CurrentWeather

取得結果例

取得結果が英語ですね…。
Location         : Tokyo International Airport, Japan (RJTT) 35-33N 139-47E 8M
Time             : Jan 29, 2013 - 12:30 AM EST / 2013.01.29 0530 UTC
Wind             :  from the W (270 degrees) at 7 MPH (6 KT) (direction variable):0
Visibility       :  greater than 7 mile(s):0
SkyConditions    :  mostly clear
Temperature      :  53 F (12 C)
DewPoint         :  10 F (-12 C)
RelativeHumidity :  17%
Pressure         :  30.12 in. Hg (1020 hPa)
Status           : Success
嫌がりそうな人が多そうなので、日本向けにでカスタムオブジェクトを生成しましょう。 表題の日本語化、温度の摂氏のみ表示、気圧にhPaのみの表示と行ったところでしょうか。
#Requires -Version 3

$web = New-WebServiceProxy -uri http://www.webservicex.net/globalweather.asmx
[xml]$xml = $web.GetWeather("Tokyo","Japan")
$xml.CurrentWeather `
    | %{
        $object = [psCustomObject]@{
            場所=$_.Location;
            時刻=$_.Time;
            風向=$_.Wind;
            視程=$_.Visibility;
            天候=$_.SkyConditions;
            温度=$_.Temperature -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
            露点温度=$_.DewPoint -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
            湿度=$_.RelativeHumidity;
            気圧=$_.Pressure -replace "[\d].[.][\d].[' ']in[.][' ']Hg[' '][(]","" -replace "[)]",""
            }

        $object
    }
日本語結果は、こんな感じで。
場所   : Tokyo International Airport, Japan (RJTT) 35-33N 139-47E 8M
時刻   : Jan 29, 2013 - 01:00 AM EST / 2013.01.29 0600 UTC
風向   :  from the SSW (200 degrees) at 13 MPH (11 KT):0
視程   :  greater than 7 mile(s):0
天候   :  mostly clear
温度   :  11 C
露点温度 :  -7 C
湿度   :  27%
気圧   :  1020 hPa
先ほどのGet-CityCountry と組み合わせると各都市の取得も簡単ですね。
#Requires -Version 3

$CityCountry = Get-CityCountry

$CityCountry `
    | %{ $web.GetWeather($_.City,$_.Country) `
        | %{
            $xml = [xml]$_
            $xml.CurrentWeather `
                | %{
                    $object = [psCustomObject]@{
                        場所=$_.Location;
                        時刻=$_.Time;
                        風向=$_.Wind;
                        視程=$_.Visibility;
                        天候=$_.SkyConditions;
                        温度=$_.Temperature -replace "[\d].[' ']F[' '][(]","" -replace "[)]","";
                        露点温度=$_.DewPoint -replace "[\d].[' ']F[' '][(]","" -replace "[)]","";
                        湿度=$_.RelativeHumidity;
                        気圧=$_.Pressure -replace "[\d].[.][\d].[' ']in[.][' ']Hg[' '][(]","" -replace "[)]",""
                        }

                    $object
                }

            }
        } | Format-Table

Function化

さて、せっかくなので流用できるように日本語版をFunction化します。
Fukui Airportを初めとして、いくつかの都市がNo Data Found返すため、[xml]キャストに失敗します。 Fukue Airportって長崎県五島市にある地方管理空港はでるのに…って、福井空港は定期便が…… ( これらに関してはtry~catch~finallyで例外処理しています。
#Requires -Version 3

function Get-Weather{

    [CmdletBinding()]
    param(
    [parameter (Position=0,Mandatory=$true,ValueFromPipeline=$true)]
    [string]$City,
    [parameter (Position=1,Mandatory=$true,ValueFromPipeline=$true)]
    [string]$Country
    )

    begin{

        if ($web -eq $null) {
            $web = New-WebServiceProxy -uri http://www.webservicex.net/globalweather.asmx
        }
    }

    process{

        $web.GetWeather($City,$Country) `
            | %{
                try
                {$xml = [xml]$_
                }
                catch [Exception]
                {
                    $Error = $_.Excption.Message
                    #Data Not Foundの際にスキップ
                }
                finally
                {
                    $xml.CurrentWeather `
                        | %{
                            $object = [psCustomObject]@{
                                場所=$_.Location;
                                時刻=$_.Time;
                                風向=$_.Wind;
                                視程=$_.Visibility;
                                天候=$_.SkyConditions;
                                温度=$_.Temperature -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
                                露点温度=$_.DewPoint -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
                                湿度=$_.RelativeHumidity;
                                気圧=$_.Pressure -replace "[\d].[.][\d].[' ']in[.][' ']Hg[' '][(]","" -replace "[)]",""
                                }

                            $object
                        }

                }
            }
        }

}
これで、以下の一文でその都市の天気が取得できます。
Get-Weather -City Tokyo -Country Japan

まとめ

New-WebServiceProxyの利用によるWeb Serviceの練習になりました。 2つのFunctionを組み合わせれば、一文で各国のそれぞれで天気を一覧取得できます。
#Requires -Version 3

function Get-CityCountry{

    [CmdletBinding()]
    param(
    #引数がなかった場合はJapanを指定
    [parameter (Position=0,ValueFromPipeline=$true)]
    [string]$Country="Japan"
    )

    begin{
        $web = New-WebServiceProxy -Uri http://www.webservicex.net/globalweather.asmx
    }

    process{

        $web.GetCitiesByCountry($Country) `
            | %{([xml]$_).NewDataSet.Table} `
            | sort City
    }

}

function Get-Weather{

    [CmdletBinding()]
    param(
    [parameter (Position=0,Mandatory=$true,ValueFromPipeline=$true)]
    [string]$City,
    [parameter (Position=1,Mandatory=$true,ValueFromPipeline=$true)]
    [string]$Country
    )

    begin{

        if ($web -eq $null) {
            $web = New-WebServiceProxy -uri http://www.webservicex.net/globalweather.asmx
        }
    }

    process{

        $web.GetWeather($City,$Country) `
            | %{
                try
                {$xml = [xml]$_
                }
                catch [Exception]
                {
                    $Error = $_.Excption.Message
                    #Data Not Foundの際にスキップ
                }
                finally
                {
                    $xml.CurrentWeather `
                        | %{
                            $object = [psCustomObject]@{
                                場所=$_.Location;
                                時刻=$_.Time;
                                風向=$_.Wind;
                                視程=$_.Visibility;
                                天候=$_.SkyConditions;
                                温度=$_.Temperature -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
                                露点温度=$_.DewPoint -replace "([\d].|[\d]|[\d]{2}.[\d])[' ']F[' '][(]","" -replace "[)]","";
                                湿度=$_.RelativeHumidity;
                                気圧=$_.Pressure -replace "[\d].[.][\d].[' ']in[.][' ']Hg[' '][(]","" -replace "[)]",""
                                }

                            $object
                        }

                }
            }
        }

}
以下の一文で天気情報を取得出来ます。
Get-CityCountry -Country "Japan" | %{ Get-Weather -City $_.City -Country $_.Country } | Format-Table
あるいはリスト表示もいいですね。
Get-CityCountry -Country "Japan" | %{ Get-Weather -City $_.City -Country $_.Country } | Format-List

参考サイト

PowerShell – 国の主要な都市を取得する [PowerShell V2 CTP3] try – catch – finally 連想配列を変換してユーザー定義オブジェクトを簡単に作成する ハッシュテーブルからカスタムオブジェクトへのキャスト(V3) 作ってから以下のサイトもあることに気づきしょぼーん。 Hey, Scripting Guy! Web サービスを使用して特定の都市の天気を確認する方法はありますか