.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から引っこ抜いてこれる。