だるろぐ

明日できることは、今日しない。

WebMatrix: 伊予鉄も止まったので、早速、遅延情報をゲットしてみる。

f:id:daruyanagi:20150126102626p:plain

WebMatrix: JR四国が止まったので、運行情報の取得プログラム作るのが捗った。 - だるろぐ で喜んでたら、今朝は伊予鉄にも遅れが出た。これで、伊予鉄の運行情報もとれるぞ!

伊予鉄の運行情報ページの構造は、

<p class="about">電車・バス 現在通常通り運行しております。</p>
<p class="date">2015/01/26(月) 10:26</p>

<!-- 遅延がある場合だけ↓ -->
<table class=default>
:
:
</table>

こんな感じになってるみたい。ということは、このテーブルがある前提で遅延情報を解析・出力、途中で例外が発生すれば正常運行とみなすという方針でよさそうだ。

public static List<DelayInfo> GetIyotestu()
{
    const string name = "伊予鉄";
    const string url = "http://www.iyotetsu.co.jp/kinkyu/";

    return GetDelayInfo(name, url, Encoding.UTF8, _ => 
    {
        var doc = new HtmlAgilityPack.HtmlDocument();

        doc.LoadHtml(_);

        try
        {
            // 遅延情報のテーブルを取得。発見できなければ例外 → 正常運行
            var rows = doc
                .DocumentNode
                // table.default のなかにある tr タグを取得
                .SelectNodes(@"//table[@class=""default""]//tr")
                // テキストノードなどは読み飛ばす
                .Where(n => n.NodeType == HtmlNodeType.Element);

            var result = new List<DelayInfo>();

            foreach (var row in rows)
            {
                var td = row.ChildNodes
                    // テキストノードなどは読み飛ばす
                    .Where(n => n.NodeType == HtmlNodeType.Element)
                    // セルの結合があるので、ほしい情報のインデックスが列によって違う!
                    // → 後ろから読む
                    .Reverse() 
                    .ToList();

                result.Add(
                    new DelayInfo()
                    {
                        Line = td[1].InnerHtml,
                        Status = td[0].InnerHtml.IndexOf("通常運行") < 0
                            ? "運休・遅延あり"
                            : "正常運行",
                        Message = td[0].InnerHtml,
                    }
                );
            }

            return result;
        }
        catch
        {
            // p.about の内容を解析して、正常運行というデータを返す    
            var text = doc.DocumentNode
                .SelectSingleNode(@"//p[@class=""about""]")
                .InnerText;
            var line = text.Split(' ')[0];
            var message = text.Split(' ')[1];
            return new List<DelayInfo>()
            {
                new DelayInfo()
                {
                    Line = line,
                    Status = "正常運行",
                    Message = message,
                },
            };
        }
    });
}

GetDelayInfo(name, url, encodsing, processor) は、指定した URL からソースコードの取得を取得するもので、キャッシュを Get/Set も行う(定型処理なので分離した)。HTML の解釈を string processor(string src) に委譲しているので、今回はその中身だけを書けばよい。

とくに難しいことはないのだけど、ただ一点、テーブルのセルがところどころ結合されている関係で、列によって取得したい情報のセルのインデックスがずれる。しかし、後ろから数えた場合のインデックスは変わらないので、Reverse() してから読んでやればいい。

f:id:daruyanagi:20150126104125p:plain

これで数日様子を見てみる。