下のWebBrowserを使ったデータ取得の質問に興味を持ち自分もやってみようと思い
ランキングのデータ収集を考えたのですが
WebBrowser1.Document.body.innerTEXTだと
これが
<tr><td>順位</td><td>ID</td><td>点数</td></tr>
<tr><td>1</td><td>フィート</td><td>35</td></tr>
このように
順位ID点数
1フィート35
なってしまいます。
リンクは個別にデータを取得できることは分かりましたが、
表は無理ですか?
意味がちょっと判らないのですが、
順位 -> 1
ID -> フィート
点数 -> 35
という表のデーターは取れていると思いますが。
すみません意味が判りました
WebBrowser.Document.body.outerhtml
でとってタグを解析したらどうでしょう。
DAO を使ってHTMLファイルのテーブルデータを取得するのが簡単かと。
> 表は無理ですか?
とれますよ。
HTMLのTABLEエレメントは、DHTMLの「tableオブジェクト」として取得できます。
tableオブジェクトは、THEADエレメントを表す「tHeadプロパティ」と、TFOOTエレメントを表す「tFootプロパティ」、そして、TBODYエレメントのコレクションを表す「tBodiesプロパティ」を持っています。
さらに、tBodiesプロパティから「tBodiesコレクション」が得られ、そこから個々の「tBodyオブジェクト」を取得できます。
そして、table、tHead、tFoot、tBodyそれぞれのオブジェクトは、各行を表す「rowsプロパティ」を持っています。(これは、TRエレメントのコレクションを表しています)
また、rowsプロパティから「rowsコレクション」が得られ、そこから個々の「trオブジェクト」を取得できます。
で、trオブジェクトは、さらに、各セル…すなわちtd(あるいはth)エレメントを表す「cellsプロパティ」を持っています。
これらを使う事で、個々のセルの内容を容易に取得・設定できます。また、セルや行の追加や削除も可能です。
各プロパティ等については、下記を参考にしてください。
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpisdk/dhtml/references/objects/objects.asp
http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/objects/table.asp?frame=true
WebBrowser.Document.body.outerhtmlでやろうとしたのですが直接とる方法はないものかと思い質問しました。
DAOで検索で調べましたが初心者に優しいサイトがなかったです・・(泣)
エレメントですけど、
こんな感じで書けばいいんでしょうけど、動く気配がないです。
Private Sub Form_Load()
WebBrowser1.Navigate "http://www.yahoo.co.jp"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Text1.Text = WebBrowser1.Document.body.Table.tBody.rows
End Sub
> DAOで検索で調べましたが初心者に優しいサイトがなかったです・・(泣)
DAO、あるいは、ADO + Jet OLEDB(Engine Type は &H80を指定)での取得は、
単純なHTML表の場合は有効ですが、結合列を含むような複雑な表の場合は
期待した結果にはならない事があります。汎用性という面ではお奨めしません。
> こんな感じで書けばいいんでしょうけど、動く気配がないです。
> Text1.Text = WebBrowser1.Document.body.Table.tBody.rows
……考え方としては間違っていませんが、記述は正しくありませんね。(^^;
# まずは、先に掲載したページ(Internet SDK)を良く見てください。
# bodyオブジェクトに、Tableプロパティという物はありませんよ。
# (Internet SDKは、お手持ちのMSDNライブラリにも掲載されていると思います)
DHTMLにて、任意のエレメント(この場合はTABLEエレメント)を取得する方法は
幾つかありますが、代表的な物を幾つか挙げてみますと、
getElementByIdメソッド
getElementsByNameメソッド
getElementsByTagNameメソッド
allコレクション
などを使う方法が用意されています。
で、とりあえずまずは、TABLEエレメントを
Dim objTable As Object
のような変数に Set してください。例えばこんな感じです。
Dim objTables As Object
Dim objTable As Object
Set objTables = Me.WebBrowser1.Document.getElementsByTagName("TABLE")
Debug.Print "TABLEの数:", objTables.length
If objTables.length > 0 Then
Set objTable = objTables(0) '最初のTABLEエレメントを取得
End If
———しかし、もしもTable要素を取得できていたとしても、先の
> Text1.Text = WebBrowser1.Document.body.Table.tBody.rows
というコードには、まだ問題が残されていたりします。
まず、このコードでは Table.tBodyというコードが書かれていますが、
私の先の回答には、「tBodyプロパティ」という記述は無かったはずです。
回答にあったのは、tBodiesプロパティでしたよね?
また、rowsプロパティが返すものは、「TRオブジェクトのコレクション」です。
コレクションをそのまま Text1.Text に表示する事はできないのです。(※1)
さて、ここで少し、HTMLテーブルの構造を説明させてください。(※2)
* HTMLの文法的には、TABLEエレメントは、その下に
* 0個または1個の<CAPTION> ……表題部
* 0個以上の<COL>または<COLGROUP> ……列定義部
* 0個または1個の<THEAD> ……ヘッダ部
* 0個または1個の<TFOOT> ……フッタ部
* 1個以上の<TBODY> ……明細部
* というエレメントが、この順番で配置されていなければいけません。
*
* ただし、THEADエレメントもTFOOTエレメントもなく、かつTBODYエレメントが
* 一つしか含まれないテーブルの場合だけは、TBODYの記述を省略する事ができ、
* その場合だけは、TABLE の直下に TR が来る事ができる事になっています。
さて、上記のTABLE構造を踏まえた上で、VBのコーディングに話を戻します。
まず、この『1個以上の<TBODY>』を取得するための記述が、
先に回答した「tBodies」というプロパティとなります。
例えば、TABLE内の最初の TBODY を取得するためには、
Dim objTBodies As Object
Dim objTBody As Object
Set objTBodies = objTable.tBodies
Debug.Print "TBODYの数:", objTBodies.length
Set objTBody = objTBodies(0)
のようになります。(※3)
で、上記のように tBodyオブジェクト を取得した後は、
Set objRows = objTBody.rows
Debug.Print "TRの数:", objRows.length
Set objRow = objRows(0)
という感じで、TBODYの下にある、最初のTRオブジェクトを取得できます。(※4)
同様に、cellsプロパティを使って、
Set objCells = objRow.cells
Debug.Print "セルの数:", objCells.length
Set objCell = objCells(0)
という感じで、TRの下にある、最初のTD(またはTH)オブジェクトを取得できます。
あとは、このセルの innerText、innerHTML、outerHTML プロパティなどで
テキストを取得したり、あるいは firstChild、childNodex、allプロパティなどで
その下にある別のエレメントを拾うなどしていけば、望む物が出来ると思います。
例えば、HTML中に含まれる最初のTABLEエレメントを取得し、その一番左上のセルの
テキストの内容を取得する場合は、以下のようになります。
Set objTables = Me.WebBrowser1.Document.getElementsByTagName("TABLE")
Text1.Text = objTables(0).rows(0).cells(0).innerText
-----------
(※1) rowsコレクションを、そのまま表示する事はできない、と書きましたが、
実際には、DHTMLのほぼ全てのオブジェクトが、規定の「toStringメソッド」を
持っており、ここから自動的に"[object]"という文字列が返されるようになっています。
ですから、もしも先のコードが、正しくrowsコレクションを取得していたのならば、
Text1.Text = objTBody.rows.toString()
のような意味として実行され、Text1には"[object]"という文字列が表示されます。
(※2) いちいち、HTMLの文法構造まで持ち出すのは冗長かとも思いましたが、
DHTMLは、HTMLをプログラムから操作できるような物なので、HTMLの構造を
理解しておいてもらった方が、解説しやすかったのです。
(※3) なお、『TABLEの直下に TBODYが無い場合(TABLEの直下にTRがある場合)』でも、
tBodiesプロパティを利用して、tBodyオブジェクトを取得することができます。
これはHTMLテーブルの構造の解説でも述べたように、TABLEの直下にTRがある場合というのが
すなわち、「TBODYの記述が省略されているだけの状態」であるため、結果として、
objTable.tHead → これは、Nothing を返す
objTable.tFoot → これも、Nothing を返す
objTable.tBodies → これは、tBodyのコレクションオブジェクトを返す
objTable.tBodies.length → 省略されたTBODYは1つだけなので、これは1を返す
のようなオブジェクト構造となるからです。
(※4) 同様に、Set objRows = objTable.rows という感じで、tableオブジェクトから、
直接TRオブジェクトのコレクションを取得する方法もあります。
tHead、tBody、tFootに対するrowsコレクションの場合は、それぞれの直下にあるTRのみを
その範囲としますが、tableオブジェクトのrowsコレクションの場合は、それら全てを
含んだ、表全体の行(trオブジェクト)を含んでいる事になります。
ありがとうございます。ちょっと時間がかかりそうなのでじっくり読んでから来ます。
↑読みきりました。何度か実験して全ての物を取得できそうな感じがしました。TableのなかのTableも取得できました。
Objectを使ったものは初めてなんですけど、下の式で開始ボタンを押すと必ず
「実行時エラー'91'
オブジェクト変数またはWithブロック変数が設定されていません。」
と表示されます。デバックから再度、開始ボタンを押すとうまく表示されるのですが、exeファイルにしたときバグって使えません。なにかが足りないのは分かるのですが何が足りないのかわかりません。
Private Sub Form_Load()
WebBrowser1.Navigate "http://www.yahoo.co.jp/"
Dim objTables As Object
Dim objTable As Object
Set objTables = WebBrowser1.Document.getElementsByTagName("TABLE")
If objTables.length > 0 Then
Text1.Text = objTables(1).rows(0).cells(0).innerTEXT
End If
End Sub
だれかお願いします。
ここのランキング取得したいです。
Private Sub Form_Load()
WebBrowser1.Navigate "http://www.e-typing.ne.jp/index.asp?mode=levelcheck&state=rank"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Dim objTables As Object
Dim objTable As Object
Set objTables = WebBrowser1.Document.getElementsByTagName("TABLE")
If objTables.length > 0 Then
Set objTable = objTables(12)
Set objTables = objTable.getElementsByTagName("TABLE")
For i = 1 To 50
For j = 0 To 2
Text1.Text = Text1.Text + objTables(1).rows(i).cells(j).innerTEXT + " "
Next j
Text1.Text = Text1.Text + Chr(13) + Chr(10)
Next i
End If
End Sub
言い忘れていました。症状は上と同じように
Objectを使ったものは初めてなんですけど、下の式で開始ボタンを押すと必ず
「実行時エラー'91'
オブジェクト変数またはWithブロック変数が設定されていません。」
と表示されます。デバックから再度、開始ボタンを押すとうまく表示されるのですが、exeファイルにしたときバグって使えません。なにかが足りないのは分かるのですが何が足りないのかわかりません。
です
コンパイルして実行してみましたが問題なく実行できてます。
コマンドボタンを押した後の処理はどうなってるのですか?
たしかWebBrowser1_DocumentCompleteは完全に終了されてなくても
発行されることがあったと思います。
もしそれが原因なら
Private Sub Form_Load()
Me.Show
WebBrowser1.Navigate "http://www.e-typing.ne.jp/index.asp?mode=levelcheck&state=rank"
Do While WebBrowser1.Busy
DoEvents
Loop
End Sub
としてみるか・・・
Private Sub WebBrowser1_ProgressChange(ByVal Progress As Long, ByVal ProgressMax As Long)
If Progress = -1 Then
Dim objTables As Object
Dim objTable As Object
Set objTables = WebBrowser1.Document.getElementsByTagName("TABLE")
If objTables.length > 0 Then
Set objTable = objTables(12)
Set objTables = objTable.getElementsByTagName("TABLE")
For i = 1 To 50
For j = 0 To 2
Text1.Text = Text1.Text + objTables(1).rows(i).cells(j).innerTEXT + " "
Next j
Text1.Text = Text1.Text + Chr(13) + Chr(10)
Next i
End If
Set objTables = Nothing
Set objTable = Nothing
End If
End Sub
で、試してみてください。
m(_ _)mすみません。
はやとちりです。
フィートさんと同じError発生しました。
Set objTables = objTable.getElementsByTagName("TABLE")
を取得してる最中にFor〜Nextがはじまってるようです。
ちょっと待機させる方法もありますが、もっといい方法が
あると思いますので・・。
m(_ _)mまたまたすみません。
>Set objTables = objTable.getElementsByTagName("TABLE")を取得してる最中
ではなくて、objTables(1).rows(i)が50ないときに発生してました。
Dim objTables As Object
Dim objTable As Object
On Error Resume Next
Set objTables = WebBrowser1.Document.getElementsByTagName("TABLE")
Text1.Text = ""
If objTables.length > 0 Then
Set objTable = objTables(12)
Set objTables = objTable.getElementsByTagName("TABLE")
For i = 1 To 50
For j = 0 To 2
Text1.Text = Text1.Text + objTables(1).rows(i).cells(j).innerTEXT + " "
Next j
Text1.Text = Text1.Text + Chr(13) + Chr(10)
Next i
End If
If Err.Number Then Err.Clear
Set objTables = Nothing
Set objTable = Nothing
こんな感じでとりあえず回避できますか?
ふぅむ……開発環境で動くという事は、取得のタイミングなのでしょうかね。
とりあえず当方で、下記のコードをコンパイルして実行してみましたが、
今の所、エラーは発生していないようです。
Option Explicit
Private Sub Form_Load()
WebBrowser1.Navigate "http://www.e-typing.ne.jp/index.asp?mode=levelcheck&state=rank"
End Sub
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
Dim objElement As Object
Dim objRow As Object
Dim objCells As Object
Set objElement = WebBrowser1.Document.getElementsByName("1")(0)
If objElement Is Nothing Then
Exit Sub
End If
Do Until objElement.tagName = "TABLE"
Set objElement = objElement.parentNode
Loop
Text1.Text = ""
Text1.Visible = False
For Each objRow In objElement.rows
On Error Resume Next
With objRow.cells
AppendText .item(0).innerText
AppendText vbTab
AppendText .item(2).innerText
AppendText vbTab
AppendText .item(1).innerText
AppendText vbNewLine
End With
On Error GoTo 0
Next
Text1.SelStart = 0
Text1.Visible = True
Set objElement = Nothing
End Sub
Private Sub AppendText(ByVal NewString As String)
Text1.SelStart = Len(Text1.Text)
Text1.SelText = NewString
End Sub
どうもみなさまありがとうございます。なんとか出来そうです。
ツイート | ![]() |