kazuakix の日記

Windows Phone とか好きです

Html Agility Pack で HTML を解析してみる

Html Agility Pack を使うことでユニバーサル アプリでも お手軽に HTML を解析することができます。

使い方は id:ch3cooh393 先生がまとめてくださっていました。

XPath を指定することで簡単にノードを指定することができるようですね。*1
 
でも、試しにプロジェクトに追加した html ファイルを解析してみようとしたところ...

var installedFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var sampleFile      = await installedFolder.GetFileAsync("sample.html");

using (var stream = await sampleFile.OpenStreamForReadAsync())
{
    var doc = new HtmlAgilityPack.HtmlDocument();
    doc.Load(stream);
    foreach (var node 
        in doc.DocumentNode.SelectNodes("/html[1]/body[1]/table[1]/tr[1]/td[1]/table[1]/tr[1]/td[1]/font[1]"))
    {
        Debug.WriteLine(node.InnerText);
    }
}

SelectNodes() が無いと怒られました。

f:id:kazuakix:20150128225616j:plain

もしかして NuGet のパッケージがおかしい?とか思ったのですが、公式ページの注意書きをよく見ると「XPATH がサポートされてないからほとんどの機能は見サポートだよ、LINQ 式だけが使えるよ。」的な事が書かれていました。

Windows 8 Metro support

The Windows 8 Metro version is a mostly untested port. There is a known bug with Windows 8 Metro HttpClient and basic authentication. This client is used within the HtmlWeb class. Also XPATH is not supported and may never be supported, only LINQ expressions can be used.

メトロ ユニバーサル アプリの場合は Descendants() + LINQ で頑張るしかないようです。

using (var stream = await sampleFile.OpenStreamForReadAsync())
{
    var doc = new HtmlAgilityPack.HtmlDocument();
    doc.Load(stream);
    
    foreach (var node in doc.DocumentNode.Descendants("a"))
    {
        Debug.WriteLine(node.InnerText);
    }
}

複雑な HTML だと面倒ですが、まぁこちらの方が慣れた方法といえなくもないですね。

(追記)Windows Phone プロジェクトの場合は HtmlDocument.LoadHtml() にしないとダメみたいです。

*1:「XPath の文字列指定するのが面倒じゃねーか!」というツッコミが聞こえてきそうですが、一緒に配布されている HAP Explorer というツールで簡単に調べることができました