htmlのテキスト部分を取得したい

タグの編集
投稿者 gaten  (社会人) 投稿日時 2012/5/28 16:20:22
今、htmlのテキスト内容(具体的には、タグ以外の内容)を取得するのに、WebBrowserにそのHTMLを表示させ、WebBrowser1.Document.Body.InnerTextでテキストを取得しています。
ただ、WebBrowserを使わない方法で、同じことを行う方法はないでしょうか?
あと、WebBrowserを使用する方法では実現されていますが、文字が&や&(コード);のように記載されている場合でも、対応する文字に変換したものがほしいです。
(この変換で文字化けするような文字はHTMLに含まれないという条件でかまいません。)

環境はVB 2008 Windows XPです。
投稿者 bz9  (中学生) 投稿日時 2012/5/28 17:06:23
http://www.gizcollabo.jp/vbtomo/log/archive/vbqanda2_364_3.html
このページがもしかしたら参考になると思います

VBから IEオブジェクトを作成し、それを操作しているっぽいです。
投稿者 るきお  (社会人) 投稿日時 2012/5/28 20:36:10
なぜWebBrowserコントロールを使いたくないのでしょうか。

一応下記のような感じで詰めていけばできることはできます。

Dim internet As New Net.WebClient
Dim allHtml As String = internet.DownloadString("http://homepage1.nifty.com/rucio/main/main.htm")

'<body>~</body>を抜き出す。(簡易版。対応できない場合あり。)  
Dim regOption = System.Text.RegularExpressions.RegexOptions.IgnoreCase Or System.Text.RegularExpressions.RegexOptions.Singleline
Dim bodyContent As String = System.Text.RegularExpressions.Regex.Match(allHtml, "<body.*?>(.*?)</body>", regOption).Groups(1).Value

'スクリプトタグを除去。(簡易版。対応できない場合多々あり。)  
Dim html As String = System.Text.RegularExpressions.Regex.Replace(bodyContent, "<script.*?>.*?</script>""", regOption)

'この時点の改行を除去 
html = html.Replace(vbCrLf, "")
html = html.Replace(vbCr, "")
html = html.Replace(vbLf, "")

'改行に置換すべきタグの処理。(簡易版。対応できない場合あり。) 
'<br/> 
html = System.Text.RegularExpressions.Regex.Replace(html, "<br\s*?/{0,1}>", vbNewLine, regOption)
'</tr> 
html = System.Text.RegularExpressions.Regex.Replace(html, "</\s*?tr>", vbNewLine, regOption)
'</p> 
html = System.Text.RegularExpressions.Regex.Replace(html, "</\s*?p>", vbNewLine, regOption)
'</h1>~</h6> 
html = System.Text.RegularExpressions.Regex.Replace(html, "</\s*?h[1-6]>", vbNewLine, regOption)

'他のすべてのタグを除去して本文のみにする。(簡易版。対応できない場合あり。)  
html = System.Text.RegularExpressions.Regex.Replace(html, "</{0,1}\w+?.*?>""", regOption)

html = html.Replace("&nbsp;"" ")
html = html.Replace("&gt;"">")
html = html.Replace("&lt;""<")
html = html.Replace("&amp;""&")
html = html.Replace(vbTab, "")
投稿者 gaten  (社会人) 投稿日時 2012/5/29 12:23:41
bz9さん
書き込みありがとうございます。
ただ、IEオブジェクトを利用するよりは、WebBrowserの方が楽です。

るきおさん
書き込みありがとうございます。
WebBrowserを使いたくない理由は、対象URLをNavigateした後、DocumentCompleteを待たないとWebBrowser1.Document.Bodyを取得できないので、
他にHTMLを解析できるようなクラスがないかと思った次第です。
ちょっと難しそうですかね。
投稿者 るきお  (社会人) 投稿日時 2012/5/29 13:10:35
>WebBrowserを使いたくない理由は、対象URLをNavigateした後、DocumentCompleteを待たないとWebBrowser1.Document.Bodyを取得できないので、
上から下へ流れるようにプログラムを書けると楽ですよね。

とはいえ、このくらいのイベントならそれほど困難でもないと思います。
他にもっと良い方法はないと思うのでイベントで実装されることをお勧めします。


多分、InnerHtmlを取得した後でさらに何かの処理があるのですよね。
その処理が何かにもよりますが、それをDocumentCompletedイベントにかけるようであれば
それほどプログラムも複雑にならずに済むかと思います。
投稿者 gaten  (社会人) 投稿日時 2012/5/31 14:02:27
るきおさん
書き込みありがとうございます。
とりあえずWebBrowserを使う方法で進めていたら、思わぬ落とし穴がありました。
BackgroundWorkerのスレッドで新たなWebBrowserのインスタンスを作成したら、

「現在のスレッドはシングル スレッド アパートメントでないため、ActiveX コントロール '8856f961-340a-11d0-a96b-00c04fd705a2' をインスタンス化できません。」

というエラーになりました。
多分、BackgroundWorkerはMTAなので、BackgroundWorkerの元となるIEコンポーネントを呼び出せないということだと思いますが、
これは何か回避策はありますか?
投稿者 魔界の仮面弁士  (社会人) 投稿日時 2012/5/31 16:21:51
> WebBrowserを使わない方法で、同じことを行う方法はないでしょうか?
NTidy は如何でしょうか。
http://www.atmarkit.co.jp/fdotnet/dotnettips/863html2text/html2text.html


> これは何か回避策はありますか? 
手っ取り早い解決策としては、BackgroundWorker は使わず、
メインスレッドで DocumentComplete を捕えることでしょうか。
そのうえで、テキストの取得処理を DocumentComplete イベントに移動させれば OK かと。


InternetExplorer を使うにしろ WebBrowser を使うにしろ、HTML を解釈するための
アンマネージの HTMLDocument オブジェクト自体が、メッセージループを必要としたはず…。