テスターですが何か?

ホビープログラマ略してHPです

気象庁のサイトから過去の気温データを取得するサンプルプログラム

leave a comment »

6/23, 24は関東地方で軒並み30度を超えて、今年一番の電力使用量になりました。(6/23 4225万kw/h、6/24 4389kw/h)

前からやりたいとおもっていた、気温と電力使用量の相関関係を可視化させる機能の実装を始めたいと思います。

過去の気象データを公開しているところといえば...そう、まず思いつくのは気象庁のサイトですね。気象庁のトップページから「気象統計情報」-「過去の気象データ検索」から、地点、年月日、データの種類(1時間ごとの値を表示)を選ぶと、以下のように1時間ごとの気象データを参照することができます。

image

ただ、APIを公開していないんですよね。なので、この画面のHTMLをパースしてデータのみを取得する必要があります。まずは、この画面に直接リンクできるかどうかを考えてみます。この画面のURLは以下のようになっています。

http://www.data.jma.go.jp/obd/stats/etrn/view/hourly_s1.php?prec_no=44&prec_ch=%93%8C%8B%9E%93s&block_no=47662&block_ch=%93%8C%8B%9E&year=2011&month=6&day=24&elm=hourly&view=

で、URLデコードするとこのようになります。

http://www.data.jma.go.jp/obd/stats/etrn/view/hourly_s1.php?prec_no=44&prec_ch=東京都&block_no=47662&block_ch=東京&year=2011&month=6&day=24&elm=hourly&view=

このURLから予想できるのは、year,month,dayのパラメーターを変えれば指定した日付のデータを直接表示できそうです、で、やってみます。見えました、6月25日の気象データ画面を表示できました。

image

次はこのHTMLをパースする方法を考えます。Watinを使えば、こんな作業造作もないのですが、Azureサーバー上でIEが起動してしまうのでちょっと...HTMLパース用のライブラリを使おうと思いますが、僕は自称現代っ子なのでHTMLの構造を意識しつつ、getElementByIdを連発してパースすることはしたくありません。Linq To HTMLがあればなぁ...と思いながら調べてみました。

ありました、SGMLReaderです。このライブラリはHTMLドキュメントをXMLドキュメントにしてくれるので、LinqToXMLを使ってHTMLをパースすることができます。時間がなくなってきたので、ソースを丸ごと貼り付けます、コメントも適当に付けたので読める人なら読めるのではないかと思います。

 

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using Sgml;
using System.Xml.Linq;

namespace MeteorologicalGetter
{
    class Program
    {
        private static string UrlFormat = "http://www.data.jma.go.jp/obd/stats/etrn/view/hourly_s1.php?prec_no=44&prec_ch=%93%8C%8B%9E%93s&block_no=47662&block_ch=%93%8C%8B%9E&year={0}&month={1}&day={2}&view=p1";

        static void Main(string[] args)
        {
            // 気象データを取得したい日付
            DateTime Target = DateTime.Parse("2010-03-22 00:00:00");

            // XML形式で1時間ごとの気象データを取得する
            var doc = GetConvertedXMLDocument(Target);
            var ns = doc.Root.Name.Namespace;

            // 1時間ごとの気象データ一覧部分の抽出
            var tr = (from p in doc.Descendants(ns + "tr")
                      where (string)p.Attribute("class") == "mtx"
                      select p).Skip(2);

            Console.WriteLine(Target.ToString("yyyyMMdd") + "の気温データ");

            int Hour = 1;

            // 気温データの抽出
            foreach (var data in tr)
            {
                var td = data.Descendants(ns + "td").ToArray();

                var Temp = td[4].Value;
                Console.WriteLine(Hour.ToString() + "時の気温:" + Temp.ToString() + "℃");

                Hour++;
            }
        }

        public static XDocument GetConvertedXMLDocument(DateTime target)
        {
            string Url = string.Format(UrlFormat, target.Year.ToString(), target.Month.ToString(), target.Day.ToString());
            XDocument doc = null;

            // WebClientを使ってHTTPレスポンスBodyを取得
            using (var stream = new WebClient().OpenRead(Url))
            {
                using (var reader = new StreamReader(stream, Encoding.GetEncoding("Shift_JIS")))
                {
                    // SGMLReaderの準備
                    var sgmlReader = new SgmlReader();
                    sgmlReader.DocType = "HTML";
                    sgmlReader.CaseFolding = CaseFolding.ToLower;
                    sgmlReader.InputStream = reader;

                    // HTMLをXML形式にする
                    doc = XDocument.Load(sgmlReader);
                }
            }

            return doc;
        }
    }
}

実行してみると、HTMLページから気温データを抽出できていることがわかります。

image

 

今回作成したソースはSkyDriveにアップしておきます。興味のある方はこちらからダウンロードしてみてください。SkyDriveがリニューアルされてダウンロードリンクが分かりにくくなっています。「ダウンロード」リンクがページ右側にあるので、そちらからダウンロードしてください。

image

今回のエントリーは以上です。

Written by david9142

2011年6月26日 @ 2:58 PM

カテゴリー: c#, LightElectricity

Tagged with , ,

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。