Xamarin.FormsでHtmlAgilityPackでXPathを使う

以前Xamarin.FormsとHtmlAgilityPackでスクレイピング!でHtmlAgilityPackをXamarinで使うとXPathが使えないよという話を書きました。Xamarin勉強会でLT用に調べ直したところ、無事XPathが使えたのでスライドを再編集して記事にしておきます。

LT当時と比べて更に状況が変化したので内容が少し変わってます。環境はVisual Studio 2017で確認しています。

やりたいこと

スクレイピングなどの際にHtmlを解析したいことがあります。HtmlAgilityPackはそんなときに使える.NET用のライブラリです。
他にもいくつか解析ライブラリはあるのですが、最も活発にメンテナンスされている、著名なものだとHtmlAgilityPackになるようです。

HTMLを解析する時、一般的なライブラリではCSSと同じ方法で指定できるCSS Selectorを利用します。しかし、HAPでは現在未対応です。
代わりにLINQやXPathを利用できます。それぞれ用途が違い、

の順にHTMLに特化していき、短く、わかりやすく書くことができます。

以前の状況

上記のブログポストで書いたとおり、現状の安定版ではXamarinではXPathを使うことができません。

理由としては、HAPは内部で標準ライブラリであるSystem.Xml.XPathを利用しています。しかし、.NETの各種実装の共通APIを定めている.NET StandardでSystem.Xml.XPathに対応するのは.NET Standard1.3以降です。現在の安定版をNugetインストールするとこの手前、WindowsPhoneあたりの非対応時代にXPath機能を省いたものが入ります。

ではXamarinの.NET Standardのバージョンはいくつか?.NET Standard | Microsoft Docs
見ればわかるように、Xamarin(iOS/Android/UWP)は対応の最小バージョンは1.4であり、System.Xml.XPathは使えるのです。

現状

さて、これを調べたちょうどよいタイミングでIssueが挙がって.NET Standard1.3に対応するよ!と宣言がありました。

Does it support .net core ?? · Issue #13 · zzzprojects/html-agility-pack

勉強会の地点ではまだ公開されていなかったのですが、現在の最新ベータ版では.NET Standard1.3に対応したものがNugetに挙がって言います。

Sharedプロジェクトの場合はすべてのプロジェクトに追加する必要があるので、「ソリューションのNuGetパッケージの管理」からすべてのプロジェクトに追加する必要があるので注意が必要です。

ソリューションのNuGetパッケージの管理

Nugetの画面で「プレリリースを含める」にチェックを付けて最新版を選択してください。現在は「1.5.0-beta92」です。これだけで準備完了です。

プレリリースを含める

あとは、共通のプロジェクトなり各個別のプロジェクトでHtmlAgilityPack以下の名前空間を使用可能です。なお、もしUWPで依存関係のエラーが出る場合、System.Xml.XPathとSystem.Net.HttpをNuGetからインストールする必要があるかもしれません。

##ソース 一応、前回のブログの記事のSearchメソッドを再実装したので載せておきます。

XPathの利用のほか、HttpClientで処理していたのをHtmlAgiliyPack.HtmlWebを利用するように変更しています。

HAPの各関数は結構独特で、空リストや例外発生ではなくnullを返すパターンが多いです。最近のC#ではNull条件演算子(?./?[)やnull合体演算子(??)が使えるのでこれはこれで扱いやすいですが、思ってもないところでぬるぽしがちなので注意してください。

まとめ

CodePlexからGitHubに移動して、ソーシャルプログラミングがやりやすくなりましたね。CSSセレクタ対応にも期待したいです。