"ブログスクレイプ"というツールを作成しました。
その時に
"Html Agility Pack"というHTMLパーサ(HTML解析ツール)を使ったので、
ノウハウをまとめておきたいと思います。
"Html Agility Pack"については、
以下のサイトを参考にさせて戴きました。ありがとうございます。
・Html Agility Pack公式サイト
・マイコミジャーナルさん
.NET向けHTMLパーサー「Html Agility Pack」で簡単スクレイピング
・neue ccさん
C#でスクレイピング:HTMLパース(Linq to Html)のためのSGMLReader利用法
開発環境は以下の通りです。
・Microsoft Visual C# 2005 Express Edition
・Windows Vista Ultimate SP2
以下、コードの説明をしていきます。
※ブログ用にコードを編集しているので、おかしな箇所があるかもしれません。。
1.URLを直接"Html Agility Pack"に渡しても良いのですが、
文字コードによって文字化けしてしまうので、
文字化け対策としてStreamReaderを使用して、
文字コード(EUC)を使用してHTMLを取得しています。
(文字化け対策)
//Uriクラスに格納
String strUri = this.txtUrl.Text;
System.Uri uri = new System.Uri ( strUri );
//Webサイトに接続してHTMLを取得
System.Net.WebClient web = new System.Net.WebClient();
//指定の文字コードでHTMLを取得する
Stream st = web.OpenRead( uri.AbsoluteUri );
StreamReader sr = new StreamReader( st, Encodeing.GetEncoding( 51932 ));
String html = sr.ReadToEnd();
sr.Close();
st.Close();
String strUri = this.txtUrl.Text;
System.Uri uri = new System.Uri ( strUri );
//Webサイトに接続してHTMLを取得
System.Net.WebClient web = new System.Net.WebClient();
//指定の文字コードでHTMLを取得する
Stream st = web.OpenRead( uri.AbsoluteUri );
StreamReader sr = new StreamReader( st, Encodeing.GetEncoding( 51932 ));
String html = sr.ReadToEnd();
sr.Close();
st.Close();
1.で取得したhtmlを"Html Agility Pack"に渡します。
//HtmlDocumentクラスにHTMLをセット
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml( html );
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml( html );
3.XPathを使ってコレクションを抽出します。
keywordは、
tableタグのclass要素がcontents_tableである要素を抽出するという意味。
//キーワードを設定する
String keyword = @"//table[@class=""contents_table""]";
//XPathを使ってコレクションを抽出
HtmlNodeCollection body =
doc.DocumentNode.SelectNodes( keyword );
String keyword = @"//table[@class=""contents_table""]";
//XPathを使ってコレクションを抽出
HtmlNodeCollection body =
doc.DocumentNode.SelectNodes( keyword );
4.取得したノードをforeachで出力しています。
どのノードからHTMLを取得するかによって、
node.OuterHtml、node.InnerHtmlなどを使い分けます。
//コレクションから値を取り出す
StringBuilder strTemp = new StringBuilder();
foreach( HtmlNode node in body )
{
strTemp.Append( node.OuterHtml );
}
StringBuilder strTemp = new StringBuilder();
foreach( HtmlNode node in body )
{
strTemp.Append( node.OuterHtml );
}
5.取得したHTMLをファイルに出力します。
ここではStreamWriterを使用して、文字コード(EUC)を指定しています。
(文字化け対策)
//ファイルに書き込む
StreamWriter sw = new StreamWriter ( stream, Encodeing.GetEncoding( 51932 ));
sw.Write( strTemp.ToString() );
sw.Close();
StreamWriter sw = new StreamWriter ( stream, Encodeing.GetEncoding( 51932 ));
sw.Write( strTemp.ToString() );
sw.Close();
大切なのは、
・手順3でどのコードを抜き出すか
・手順4でどのノードを出力するか
・文字化け対策
だと思います。
もっと簡単に実現できる方法があるかと思いますが、
参考程度にしていただけると助かります。
参考になりました。
返信削除1にEncodingのスペルミスがありますので、一応・・・。