BLOG

Go to top


Perl モジュール XML::Simple の基本的な使い方を知っておくと REST API とか RSS とかの扱いがとても楽になる(楽しくなるかどうかは知らん)

April 4, 2008 4:32 PM

珍しいことにあんまりにも仕事が暇だったので練習しておきました。オフィスに一人、かつやることがない状況は嬉しい人には嬉しいのかもしれませんが、僕は手持ち無沙汰な感じがして苦手です。なので、プラグイン作成をかねてやってみました。

とりあえず XML を取得してみる

題材はなんでもいいけれど、何の役にも立たないのもどうかと思うので、今回は livedoor Weather Hacks のフィードを拝借することにしました。以下のような URL で、特定の地域の明日の天気予報が取得できます。

http://weather.livedoor.com/forecast/webservice/rest/v1?city=***&day=tomorrow

「***」の部分に地域の ID 番号をいれます。ID 番号については 全国の地点定義表(RSS) 内の 「1次細分区(cityタグ)」の id 属性から拾ってきます(ブラウザが xml 用の画面になってしまう場合は、右クリックからリンク先を保存してください)。たとえば、「大阪府」の「大阪」であれば、ID 番号は「81」になるので、以下のような URL にリクエストを送り、xml を取得します。リクエストの送信には、LWP::UserAgent を使用します。

http://weather.livedoor.com/forecast/webservice/rest/v1?city=81&day=tomorrow

my $url = "http://weather.livedoor.com/forecast/webservice/rest/v1?city=81&day=tomorrow";
my $ua = LWP::UserAgent->new();
$ua->agent('Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)');
$ua->timeout(15);
$ua->env_proxy();
my $res = $ua->get($url);
$res->is_success or die 'Can\'t connect to weather.livedoor.com.';
my $xml = $res->content;

とりあえず XML の構造を見てみる

この時点で、 $xml を print してみると、以下のような構造になっています。

<?xml version="1.0" encoding="UTF-8" ?>
<lwws version="livedoor Weather Web Service 1.0">
<author>livedoor Weather Team.</author>
<location area="近畿" pref="大阪府" city="大阪" />

<title>大阪府 大阪 - 明日の天気</title>
<link>http://weather.livedoor.com/area/27/81.html?v=1</link>
<forecastday>tomorrow</forecastday>
<day>Saturday</day>
<forecastdate>Sat, 05 Apr 2008 00:00:00 +0900</forecastdate>

<publictime>Fri, 04 Apr 2008 11:00:00 +0900</publictime>
<telop>晴れ</telop>
<description>北大阪では、明日朝に霜の降りるおそれがあります。農作物の管理に注意して下さい。

近畿地方は、薄雲が広がっている所もありますが、東シナ海にある高気圧に覆...</description>
<image>
<title>晴れ</title>
<link>http://weather.livedoor.com/area/27/81.html?v=1</link>
<url>http://image.weather.livedoor.com/img/icon/1.gif</url>
<width>50</width>
<height>31</height>

</image>
<temperature>
<max>
<celsius>18</celsius>
<fahrenheit>64.4</fahrenheit>
</max>
<min>
<celsius>8</celsius>
<fahrenheit>46.4</fahrenheit>
</min>
</temperature>

<pinpoint>

<location>
<title>大阪市</title>
<link>http://weather.livedoor.com/point/city/1632.html</link>
<publictime>Fri, 04 Apr 2008 06:00:00 +0900</publictime>
</location>

<location>
<title>大阪市都島区</title>
<link>http://weather.livedoor.com/point/city/1633.html</link>
<publictime>Fri, 04 Apr 2008 06:00:00 +0900</publictime>

</location>

<location>
<title>大阪市福島区</title>
<link>http://weather.livedoor.com/point/city/1634.html</link>
<publictime>Fri, 04 Apr 2008 06:00:00 +0900</publictime>
</location>

# 中略

<location>
<title>河南町</title>
<link>http://weather.livedoor.com/point/city/1697.html</link>
<publictime>Fri, 04 Apr 2008 06:00:00 +0900</publictime>
</location>

<location>
<title>千早赤阪村</title>
<link>http://weather.livedoor.com/point/city/81.html</link>
<publictime>Fri, 04 Apr 2008 06:00:00 +0900</publictime>

</location>

</pinpoint>

<copyright>
<title>Copyright (C) 1996-2008 livedoor Co.,Ltd. All rights reserved.</title>
<link>http://weather.livedoor.com</link>
<image>
<title>livedoor 天気情報</title>
<link>http://weather.livedoor.com</link>
<url>http://image.weather.livedoor.com/img/cmn/livedoor.gif</url>
<width>118</width>

<height>26</height>
</image>
<provider name="(株)ハレックス" link="http://www.halex.co.jp/halexbrain/weather/" />
<provider name="日本気象協会" link="http://tenki.jp/" />
</copyright>

</lwws>

とりあえず XMLin してみる

この $xml を、XML::Simple の XMLin 関数でパースします。

my $data = XMLin($xml);

ここで、 $data を Data::Dumper で Dumper して print すると、ハッシュ構造になっていることがわかります。

$VAR1 = {
          'link' => 'http://weather.livedoor.com/area/27/81.html?v=1',
          'forecastdate' => 'Sat, 05 Apr 2008 00:00:00 +0900',
          'location' => {
                          'city' => '大阪',
                          'area' => '近畿',
                          'pref' => '大阪府'
                        },
          'pinpoint' => {
                          'location' => [
                                          {
                                            'link' => 'http://weather.livedoor.com/point/city/1632.html',
                                            'publictime' => 'Fri, 04 Apr 2008 06:00:00 +0900',
                                            'title' => '大阪市'
                                          },
                                          {
                                            'link' => 'http://weather.livedoor.com/point/city/1633.html',
                                            'publictime' => 'Fri, 04 Apr 2008 06:00:00 +0900',
                                            'title' => '大阪市都島区'
                                          },
                                          {
                                            'link' => 'http://weather.livedoor.com/point/city/1634.html',
                                            'publictime' => 'Fri, 04 Apr 2008 06:00:00 +0900',
                                            'title' => '大阪市福島区'
                                          },
# 中略
                                          {
                                            'link' => 'http://weather.livedoor.com/point/city/1697.html',
                                            'publictime' => 'Fri, 04 Apr 2008 06:00:00 +0900',
                                            'title' => '河南町'
                                          },
                                          {
                                            'link' => 'http://weather.livedoor.com/point/city/81.html',
                                            'publictime' => 'Fri, 04 Apr 2008 06:00:00 +0900',
                                            'title' => '千早赤阪村'
                                          }
                                        ]
                        },
          'version' => 'livedoor Weather Web Service 1.0',
          'copyright' => {
                           'provider' => {
                                           '日本気象協会' => {
                                                                     'link' => 'http://tenki.jp/'
                                                                   },
                                           '(株)ハレックス' => {
                                                                           'link' => 'http://www.halex.co.jp/halexbrain/weather/'
                                                                         }
                                         },
                           'link' => 'http://weather.livedoor.com',
                           'title' => 'Copyright (C) 1996-2008 livedoor Co.,Ltd. All rights reserved.',
                           'image' => {
                                        'width' => '118',
                                        'link' => 'http://weather.livedoor.com',
                                        'url' => 'http://image.weather.livedoor.com/img/cmn/livedoor.gif',
                                        'title' => 'livedoor 天気情報',
                                        'height' => '26'
                                      }
                         },
          'publictime' => 'Fri, 04 Apr 2008 11:00:00 +0900',
          'author' => 'livedoor Weather Team.',
          'description' => '北大阪では、明日朝に霜の降りるおそれがあります。農作物の管理に注意して下さい。

近畿地方は、薄雲が広がっている所もありますが、東シナ海にある高気圧に覆...',
          'image' => {
                       'width' => '50',
                       'link' => 'http://weather.livedoor.com/area/27/81.html?v=1',
                       'url' => 'http://image.weather.livedoor.com/img/icon/1.gif',
                       'title' => '晴れ',
                       'height' => '31'
                     },
          'telop' => '晴れ',
          'day' => 'Saturday',
          'title' => '大阪府 大阪 - 明日の天気',
          'forecastday' => 'tomorrow',
          'temperature' => {
                             'min' => {
                                        'celsius' => '8',
                                        'fahrenheit' => '46.4'
                                      },
                             'max' => {
                                        'celsius' => '18',
                                        'fahrenheit' => '64.4'
                                      }
                           }
        };

各データの取り出し方

この形にできれば、各データへのアクセスは非常に簡単です。たとえば、

'title' => '大阪府 大阪 - 明日の天気',                   

の、「大阪府 大阪 - 明日の天気」を取得したい場合は、

my $title = $data->{title};                  

と書くだけで、$title に「大阪府 大阪 - 明日の天気」が代入されます。他にも、最高気温と最低気温を取得したい場合は、

'temperature' => {
                 'min' => {
                            'celsius' => '8',
                            'fahrenheit' => '46.4'
                          },
                 'max' => {
                            'celsius' => '18',
                            'fahrenheit' => '64.4'
                          }
               }              

のブロックにアクセスします。書き方は以下のような具合です。$temp_min に最低気温(摂氏)が、 $temp_max に最高気温(摂氏)が代入されます。

my $temp_min = $data->{temperature}->{min}->{celsius};
my $temp_max = $data->{temperature}->{max}->{celsius};

あとは お天気 WEB サービス仕様 を参考に、取り出したい情報を取り出してメールで送れば、天気予報メールマガジンみたいなものくらいは作れるかもしれません。僕は Movable Type のプラグインにして、毎朝その天気を自分の携帯にメールで送ることにしました。ささやかですが案外便利です。

あと、XML::Simple には XMLout なんかの関数もありますが、これについてはまた今度。

Comments


Contact me

Copyright © 2005 - 2017 okayama All rights reserved.