以前の記事「【VB.NET】指定したURLのHTMLを取得する」の応用です。
VB 2005からSystem.Net.HTMLDocumentクラスが追加されています。
このクラスを利用することにより、DOMを扱うことができ、簡単にHTMLの解析を行うことができるようになります。
しかし、System.Net.HTMLDocumentクラス自体には、コンストラクタが存在しません。
そのため、通常は、WebBrowserコントロールを通じてHTMLDocumentクラスを生成します。
WebBrowserコントロールを使わずにHTMLDocumentを利用する方法について説明します。
※この方法は、完全な動作を保証するものではありません。
試作段階ですので、エラーが発生することがあります。
WebClientで取得したHTMLテキストをSystem.Net.HTMLDocumentに直接変換することはできません。
そのため、Microsoft.mshtml.dllに含まれているmshtml.HTMLDocumentクラスを利用して変換します。
mshtml.HTMLDocumentクラスには、writeメソッド等が用意されていません。
そのため、インターフェースのIHTMLDocument2にキャスト(型変換)して利用することになります。
以下、サンプルです。
VB 2005からSystem.Net.HTMLDocumentクラスが追加されています。
このクラスを利用することにより、DOMを扱うことができ、簡単にHTMLの解析を行うことができるようになります。
しかし、System.Net.HTMLDocumentクラス自体には、コンストラクタが存在しません。
そのため、通常は、WebBrowserコントロールを通じてHTMLDocumentクラスを生成します。
WebBrowserコントロールを使わずにHTMLDocumentを利用する方法について説明します。
※この方法は、完全な動作を保証するものではありません。
試作段階ですので、エラーが発生することがあります。
WebClientで取得したHTMLテキストをSystem.Net.HTMLDocumentに直接変換することはできません。
そのため、Microsoft.mshtml.dllに含まれているmshtml.HTMLDocumentクラスを利用して変換します。
mshtml.HTMLDocumentクラスには、writeメソッド等が用意されていません。
そのため、インターフェースのIHTMLDocument2にキャスト(型変換)して利用することになります。
以下、サンプルです。
《事前準備》
1.参照設定を追加する。
1)メニューバーの[プロジェクト]-[参照設定の追加]を選択する。
2)[.NET]タグを選択し、一覧から「Microsoft.mshtml」を選択し、[OK]ボタンを押します。
《コード》
試しにgoogleのトップページと本ブログのページをURLに指定して実行してみました。
実行結果として、href属性の値は取得できましたが、writeメソッド実行時にエラーが発生しました。
エラー内容を確認してみると、HTMLテキストで参照されているJavaScript等の解析エラーです。ということは、HTMLDocumentに出力したHTMLテキストを解析した際にエラーが見つかるとエラーダイアログを表示する仕組みとなっているようです。
これについては、描画(レンダリング)機能のないブラウザを作成しているのと変わらないので、これが正常な動作のようです。
【補足事項】
・Microsoft.MSHTML.DLLに用意されているHTMLDocumentクラスには、コンストラクタが存在します。
・COMを参照する場合、MSHTML.TLBを参照することで同じ機能を持つライブラリを参照することが出来ます。
・JavaScriptやActiveXの実行については、ブラウザの設定を利用するようです。
1.参照設定を追加する。
1)メニューバーの[プロジェクト]-[参照設定の追加]を選択する。
2)[.NET]タグを選択し、一覧から「Microsoft.mshtml」を選択し、[OK]ボタンを押します。
《コード》
Imports System
Imports System.IO
Imports System.Net
Imports System.Text
Public Class SampleHTML
Public Shared Sub main()
LoadHTML("http://blog.livedoor.jp/akf0/archives/51221988.html")
End Sub
Private Sub LoadHTML(ByVal url As String)
Dim wc As New WebClient()
Try
Dim st As Stream = wc.OpenRead(url)
Dim enc As Encoding = Encoding.GetEncoding("EUC-JP")
Dim sr As StreamReader = New StreamReader(st, enc)
Dim html As String
Dim msdoc As New mshtml.HTMLDocument
html = sr.ReadToEnd()
'以下は、どちらの方法でも可能
'�IHTMLDocument2をデータ型とする変数を宣言して処理する
Dim imsdoc As mshtml.IHTMLDocument2
imsdoc = CType(msdoc, mshtml.IHTMLDocument2)
imsdoc.write(html)
For Each link As mshtml.IHTMLElement2 In imsdoc.links
Debug.WriteLine(link.GetAttribute("href"))
Next
System.Runtime.InteropServices.Marshal.ReleaseComObject(imsdoc)
imsdoc = Nothing
'�IHTMLDocument2をデータ型とする変数を宣言せずに処理する
'CType(msdoc, mshtml.IHTMLDocument2).write(html)
'For Each link As mshtml.IHTMLElement2 In CType(msdoc, mshtml.IHTMLDocument2).links
' Debug.WriteLine(link.GetAttribute("href"))
'Next
System.Runtime.InteropServices.Marshal.ReleaseComObject(msdoc)
msdoc = Nothing
sr.Close()
st.Close()
Catch ex As Exception
Debug.WriteLine(ex.Message)
Finally
wc.Dispose()
End Try
End Sub
End Class
試しにgoogleのトップページと本ブログのページをURLに指定して実行してみました。
実行結果として、href属性の値は取得できましたが、writeメソッド実行時にエラーが発生しました。
エラー内容を確認してみると、HTMLテキストで参照されているJavaScript等の解析エラーです。ということは、HTMLDocumentに出力したHTMLテキストを解析した際にエラーが見つかるとエラーダイアログを表示する仕組みとなっているようです。
これについては、描画(レンダリング)機能のないブラウザを作成しているのと変わらないので、これが正常な動作のようです。
【補足事項】
・Microsoft.MSHTML.DLLに用意されているHTMLDocumentクラスには、コンストラクタが存在します。
・COMを参照する場合、MSHTML.TLBを参照することで同じ機能を持つライブラリを参照することが出来ます。
・JavaScriptやActiveXの実行については、ブラウザの設定を利用するようです。
- カテゴリ:
- VB.NET
ありがとうございました。
未熟者ですが私なりの改良案を・・・
・IHTMLDocument2 よりも、IHTMLDocument3の方が、getElementsByName() メソッドなどが使えて便利。IHTMLDocument3 型でも write(html) メソッドが可能。(なぜかコードインテリセンスには出てこない。)
・mshtml は非同期でファイルを読み込むらしく、読み込み完了前はエレメントなどが取得できない。そこで、while 文で IHTMLDocument3 のインスタンスのreadyState プロパティをチェックして = "complete" を待った方がよい、と思ったのですが、なぜか "complete" にならず、ずっと "loading" のまま変化しなかった。
ちなみに、readyState プロパティもコードインテリセンスには出てこないですが、実行時のウォッチ式で確認できます。
結局、while 文はコメントアウトして、"loading" のまま先に進むことにしたが、エレメントは無事取得できていた。なぜ??