2011年2月24日木曜日

.NET用のオープンソースなHTMLのパーサー : Html Agility Pack

かくかくしかじかでHTMLの解析をする必要があったのでけれど、
.NETにはXMLのパーサーはあれどもHTMLのパーサーがないので
なんかいいものがないかと探していたところ、
なかなか良さげなツールを見つけたのでそのメモ。

ちなみに、
System.Windows.Forms.HtmlDocument ってのもあるけれど、
WebBrowserコントロール経由でないとインスタンスを取得できないとか、
InternetExplorerに依存しているとか、
InternetExplorerのバージョンによって影響されるとか、
HTMLの文字列だけほしいのに画像までダウンロードしてくるので遅くて重いとか、
まぁ、もろもろの問題があるので使えない。

で、今回の本題はこっち。
Html Agility Pack
http://htmlagilitypack.codeplex.com/

.NET向けのHTMLパーサーです。
オープンソースでフリーのライブラリ。

使い方について
あんまり情報が見つからなかったので
その辺について。

まずはじめに1つ。
using HtmlAgilityPack;
と書くと、
System.Windows.Forms.HtmlDocument と曖昧な参照になってしまい
コンパイルエラーになるので、
using hap = HtmlAgilityPack;
とかしておいた方がいい。

基本的に、HTMLの解析には、
HtmlAgilityPack.HtmlDocument
というクラスを中心に使用します。

HTMLのソースは、たとえばこんな感じで取得する。
System.Net.WebClient web = new System.Net.WebClient();
string htmlSource = web.DownloadString(url);
ほかにも、ブラウザでソースを表示させてコピペとかいろいろ方法はある。

HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
html.LoadHtml( htmlSource; );

これだけで、ソースのロードは完了。

html.Load( url );
で、URLからダウンロードしてくることも出来るっぽい。

あとは、XPathという、XMLの特定の要素を指定したりするための言語を使って
目当ての要素を取得する。
XPathの詳細はgoogle先生に任せるとして、

HtmlAgilityPack.HtmlNodeCollection tags = html.DocumentNode.SelectNodes( xPath );
とすれば、該当するタグのコレクションが取得できる。

XPathは、たとえば、

HtmlAgilityPack.HtmlNodeCollection ulNodes = html.DocumentNode.SelectNodes( "//ul" );
とすれば、ページ内の
<ul> ~</ul>
でくくられた部分を一通り取得する。
さらに、

HtmlAgilityPack.HtmlNodeCollection liNodes = ulNodes[0].SelectNodes( ".//li" );
とすると、最初の<ul></ul>内の
<li></li>要素のコレクションが取得できる。

HtmlAgilityPack.HtmlNode li = html.DocumentNode.SelectSingleNode( "//ul[1]/li[2]" );
で、1つめの<ul></ul>内の
2番目の<li></li>要素を取得したりとか、

HtmlAgilityPack.HtmlNode td = html.DocumentNode.SelectSingleNode( "//table[1]//td[3]" );
で、1つめの<table></table>内に出現する3つめの<td></td>を取得したり。

HtmlAgilityPack.HtmlNode a = html.DocumentNode.SelectSingleNode( "//a[0]" );
string linkUrl = System.Web.HttpUtility.HtmlDecode( a.GetAttributeValue( "href", "" ) );
で、ハイパーリンクのアドレスを取得したりもできる。

逆に、
HtmlNode.XPathプロパティからXPathを取得することもできる。

つまるところ、XPathをうまいこと指定してやることで、
簡単にほしい情報をHTMLから引っこ抜いてこれる。