WebbrowserコントロールなしでのDHTMLの操作

解決


hiroki_kana  2004-01-06 05:33:17  No: 81245

さきほど初心者質問版で質問させていただいた者ですm(_ _)m

WebbrowserコントロールでHTMLを取得し、解析しています。
解析方法は「WebBrowserで表のデータ収集」に書いてある
方法でやっています(DHTMLでのやり方)

この方法ではWebBrowserコントロールを表示していないと
取得できないようなのです。
VisibleプロパティをFalseにしてみるとできないのです。
この場合Inetを使いたいのですがそうするとDHTMLを使用
できなくなる(Documentプロパティみたいのがない)み
たいなのでどうしようか困っています。

どうにかしてWebbrowserコントロールを使わずにDHTMLの
データを取得する方法はありませんか??

お願いします


魔界の仮面弁士  2004-01-06 07:50:25  No: 81246

IPersistFileインターフェイス、もしくはIPersistStreamInitインターフェイスのLoadメソッドを使えばOKです。
(前者はファイルからの読み込み、後者はストリームからの読み込みとなります)

例えば、以下のようにすれば、変数Docは C:\hoge.html を解析した結果となります。

    Dim Doc As MSHTML.HTMLDocument
    Dim File As IPersistFile

    Set Doc = New HTMLDocument
    Set File = Doc
    File.Load "C:\hoge.html", STGM_READ

なお、IPersistFileやIPersistStreamInitは、MSHTML.TLBファイル中では定義されていないので、タイプライブラリを別途用意し、それを参照設定しておく必要があります。


hiroki_kana  2004-01-06 08:31:53  No: 81247

すいません、タイプライブラリとはなんでしょうか??
全体的に私の勉強不足でわからないので説明していただけませんか??
すみません…


魔界の仮面弁士  2004-01-06 11:33:38  No: 81248

あ…良く見たら、開発環境が書かれていませんでしたね。
(先のコードは、VB6という前提で書いた物です)

> タイプライブラリとはなんでしょうか??
外部コンポーネントのインターフェイス……プロパティ、メソッドの戻り値やデータ型、あるいは定数などの各種情報を記述したバイナリファイルの事です。

とりあえずは、
  『[参照設定]を行う時に使うファイル(DLL、TLB、OLB等)の事』
と考えて貰えれば良いでしょう。

……ただし、IPersistFileやIPersistStreamInit等を定義したタイプライブラリは、標準では存在していませんので、それは別途(自作するなどして)用意する必要があったりします。
(VB6には、[インターフェイス]を定義するための仕組みが無いので、タイプライブラリを経由する必要があるのです)


hiroki_kana  2004-01-07 00:32:04  No: 81249

ありがとうございます。

>あ…良く見たら、開発環境が書かれていませんでしたね。
>(先のコードは、VB6という前提で書いた物です)
すみません、開発環境はVB6です。

過去ログで調べてIPersistFileについてはなんとなくわかりました。
タイプライブラリも魔界の仮面弁士さんが作ったものを使わせていただいています。

ファイルからは読み込むことができたのですがネットワークから直接取得したHTMLのデータを読み込むにはどうしたらよいのでしょうか??


魔界の仮面弁士  2004-01-07 00:33:49  No: 81250

IPersistStreamInitについて調べてみてください。


hiroki_kana  2004-01-07 01:50:07  No: 81251

何とか調べてみてコードを書いてみたのですが
「オブジェクト変数またはWithブロック変数が設定されていません。」というエラーが「Tmp.Load Stm2」の部分ででてしまいます。

    Dim InetDoc() As Byte
    Dim Stm As Object
    Dim Stm2 As IStream
    Dim Doc As MSHTML.HTMLDocument
    Dim Tmp As IPersistStream
    
    Inet1.protocol = icHTTP
    Inet1.url = "http://www.yahoo.co.jp"
    InetDoc = Inet1.OpenURL

    Set Stm = New ADODB.Stream
    Stm.open
    Stm.Type = adTypeBinary
    Stm.write InetDoc
    Stm.Close
    
    Set Stm2 = Stm
    
    Set Doc = New HTMLDocument
    Set Doc = Tmp
    Tmp.Load Stm2
    
    
    Debug.Print Doc.getElementsByTagName("TABLE").length

間違っている箇所を教えていただけないでしょうか??


魔界の仮面弁士  2004-01-07 02:51:36  No: 81252

> 間違っている箇所を教えていただけないでしょうか??

≪致命的なエラー:その1≫
宣言しているデータ型が間違っています。
名前は似ていますが、「IPersistStream」と「IPersistStreamInit」は別物です。

≪致命的なエラー:その2≫
『〜変数が設定されていません』の理由ですが、変数TmpがNothing状態なのに、そのLoadメソッドを使っているからです。
この場合は、変数DocをTmpにSetすればOKです。

≪エラーにはならないが修正が必要な点≫
IPersistStreamInit.Load の前に、ADODB.StreamのPositionプロパティを0にしておいてください。
Write直後は、カーソル位置がストリームの最後にあるので、先頭に戻しておかないと、データが正しく渡されません。

≪バグではないが、無駄な点≫
ADODB.StreamはIStreamインターフェイスを有していますので、『Set Stm2 = Stm』のようにせずとも、直接、Loadメソッドの引数に渡せますよ。


hiroki_kana  2004-01-07 05:06:38  No: 81253

できました^^ありがとうございます。
本当に助かりました^^

しかし、別の問題が発生してしまったのです…
コードは以下です。

    Dim InetDoc() As Byte
    Dim Stm As Object
    Dim Stm2 As IStream
    Dim Doc As MSHTML.HTMLDocument
    Dim Tmp As IPersistStreamInit
    
    Inet1.protocol = icHTTP
    Inet1.url = "http://www.yahoo.co.jp"
    InetDoc() = Inet1.OpenURL(, icByteArray)
    
    Set Stm = New ADODB.Stream
    Stm.open
    Stm.Type = adTypeBinary
    Stm.write InetDoc()
    Stm.position = 0

    
    Set Doc = New HTMLDocument
    Set Tmp = Doc
    Tmp.Load Stm
    Stm.Close
    Dim objTable As Object
    Set objTable = Doc.getElementsByTagName("TABLE")
    Debug.Print objTable.length

これで実行するとobjtable.lengthは0と表示されるのです。
しかし、Set objTable = Doc.getElementsByTagName("TABLE")の場所にブレークポイントをおきF8で順次実行すれば正しく表示されます。
もしかして、Set〜が実行される前にDebug.〜が実行されてるのでしょうか?


魔界の仮面弁士  2004-01-07 05:54:53  No: 81254

> Set〜が実行される前にDebug.〜が実行されてるのでしょうか?
違います。もし、Set実行前に動作しているのだたとしたら、
『オブジェクト変数またはWithブロック変数が設定されていません。』
のエラーになっているはずですよね?

> F8で順次実行すれば正しく表示されます。
MSHTMLパーサによってHTMLが解析されるには、若干の時間が必要なのです。

WebBrowserコントロールを使って処理する時にも、DocumentCompleteイベントが発生するまで、解析は完了しませんよね。それと一緒です。
Loadメソッドで読み込んだ直後は、WebBrowserでいえば、まだNavigateCompleteイベントが発生した段階に過ぎないというわけです。

'==========
Option Explicit

Private WithEvents Doc As MSHTML.HTMLDocument

Private Sub Doc_onreadystatechange()
    Debug.Print Doc.readyState
End Sub

Private Sub Command1_Click()
    Dim Stm As ADODB.Stream
    Dim StmInit As IPersistStreamInit

    Set Stm = New ADODB.Stream
    Stm.Type = adTypeBinary
    Stm.Open
    Stm.Write Inet1.OpenURL("http://www.yahoo.co.jp/", icByteArray)
    Stm.position = 0

    Set Doc = New HTMLDocument
    Set StmInit = Doc
    StmInit.Load Stm
    
    Stm.Close
    Set Stm = Nothing

    'この時点で処理しても、解析が終わっているという保証は無い。
    Debug.Print Doc.getElementsByTagName("TABLE").length
End Sub


hiroki_kana  2004-01-08 04:53:15  No: 81255

ありがとうございます^^
本当にたすかりました^^


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加