WebMatrix: JR四国が止まったので、運行情報の取得プログラム作るのが捗った。

執筆日時:

f:id:daruyanagi:20150125141900p:plain

密かに待ってました。人身事故ってのがちょっと胸痛むけれど。すみません。でも、これで運行に遅延が発生した時にどんなコードが吐かれるのかわかったやで。

遅れがないとき。

<div ID="delay_info">
<div class="no_delay">◇現在、遅れ等の情報はありません。</div>
</div>

遅れがあるとき。

<div ID="delay_info">
<p>◇現在、以下のエリアで影響が出ています(*:**更新)。</p>

<h4>徳島線</h4> <h5>徳島線(牛島駅構内) 運転再開</h5> <p>徳島線では……<br>※高徳線の列車は……</p> </div>

同じ路線で複数の遅延情報があるケースも考えられるだろうので、タグはこんな感じになるんだろう(と思う)。

p

h4
h5
p

h5
p
:
h4
h5
p

h5
p
:

というわけで、これをいい感じにデータオブジェクトに変換していくわけれだけれど、どうしよう。

とりあえず HtmlAgilityPack でやってみた。

public class DelayInfo
{
public string Line { get; set; }
public string Status { get; set; }
public string Message { get; set; }
}

public static List<DelayInfo> GetJRShikoku()
{
const string key = "jrshikoku";
const string url = "http://www.jr-shikoku.co.jp/info/";

// キャッシュを探す
var result = WebCache.Get(key) as List<DelayInfo>;

// キャッシュがヒットしなければ、情報の取得
if (result == null)
{
using (var client = new WebClient())
{
// !!
client.Encoding = Encoding.GetEncoding("Shift_JIS");

var doc = new HtmlAgilityPack.HtmlDocument();
var src = client.DownloadString(url);

doc.LoadHtml(src);

var nodes = doc.DocumentNode
// div#delay_info タグを探す
.SelectSingleNode(@"//div[@id=""delay_info""]")
// 直下のノードを列挙
.ChildNodes
// 改行・コメントなどのノードは読み飛ばす
.Where(_ => _.NodeType == HtmlNodeType.Element)
// 最初の div#no_delay や p は読み飛ばす
.Skip(1);

var line = string.Empty;
var status = string.Empty;

result = new List<DelayInfo>();

foreach (var node in nodes)
{
switch (node.Name)
{
case "h4": // 線名を記憶
line = node.InnerText;
continue;
case "h5": // "徳島線(牛島駅構内) 運転再開"を記憶
status = node.InnerText;
continue;
case "p":  // p タグを見つけたらデータをプッシュ
result.Add(new DelayInfo()
{
Line = line,
Status = status,
Message = node.InnerText,
});
break;
default:
// Do Nothing
break;
}
}

// 遅延情報が見つからなかった場合、全線正常のデータをプッシュ
if (result.Count == 0)
{
result.Add(new DelayInfo()
{
Line = "全線",
Status = "正常運行",
Message = "現在通常通り運行しております。",
});
}
}
}

return result;
}

f:id:daruyanagi:20150125143551p:plain

ビューでこのデータを適当にレンダリング。まぁ、まぁ、いい感じかもしれない。もっといろんなケースを見てみたかったけれど、とりあえずこれが正しいとして、Twitter BOT でも実装してみるかな。