5.InternetExplorer を使っての HTM ファイル内の要素を取得・操作例 |
1.InternetExplorer を使っての HTM ファイル内の全ての要素を調査 2.上記プログラム使用上の留意点 3.要素を取得してのその活用例(Yahoo メールへのログイン) 4. 5. 6. |
下記プログラムコードに関する補足・注意事項 動作確認:Windows Vista・Windows 7 (32bit) / VB6.0(SP6) Option :[Option Explicit] 参照設定:Microsoft Internet controls 参照設定方法参照 使用 API: その他 :プロジェクト→コンポーネント→コントロールで Microsoft Rich Textbox Control 6.0 にチェックを入れ、 :そして、表示された Rich Textbox コントロールをフォームに貼り付けて下さい。 |
1.InternetExplorer を使っての HTM ファイル内の全ての要素を調査 |
Option Explicit Private WithEvents IE As SHDocVw.InternetExplorer Private myURL As String Private Sub Form_Load() Command2.Enabled = False '表示されるまでは使用できないように Command3.Enabled = False Command4.Enabled = False Text1.Text = "https://login.yahoo.co.jp/config/login_verify2?.src=ym" RichTextBox1.Text = "" 'テキストボックスでは、メモリオーバーになるので Text3.Text = "ALL" End Sub Private Sub Command1_Click() Command2.Enabled = False Command3.Enabled = False Command4.Enabled = False RichTextBox1.Text = "" myURL = Text1.Text '起動中のIEを閉じる場合 If Not IE Is Nothing Then IE.Quit Set IE = Nothing End If Set IE = New SHDocVw.InternetExplorer '指定のURLを表示 IE.Navigate2 myURL IE.Visible = True 'IE を表示 End Sub Private Sub IE_DocumentComplete(ByVal pDisp As Object, URL As Variant) Debug.Print "[ " & URL & " ]" '同時にどのようなものが表示されるか確認して下さい。 If CStr(URL) <> myURL Then '指定のURL以外は除外する(広告のページやフレーム等が表示されるので) Exit Sub End If '指定のURLが表示されるまで待つ(待機関数等で表示待ちをしない事) Command2.Enabled = True Command3.Enabled = True Command4.Enabled = True End Sub Private Sub Command2_Click() Dim Element As Object Dim i As Long Dim myText As String myText = fStrCut("No.", 10) & fStrCut("要素名", 20) & fStrCut("http://www.nikkansports.com/Type", 20) & _ fStrCut("NAME", 26) & fStrCut("ID", 26) & fStrCut("value", 30) & vbCrLf Dim No As String, TN As String, ty As String, na As String, id As String, va As String With IE i = 0 '全ての要素を取得 If Text3.Text = "ALL" Then For Each Element In .Document.All '要素によっては、エラーが発生するので別処理で If TypeName(Element) = "HTMLIFrame" Then No = fStrCut(CStr(i), 10) TN = fStrCut(Element.tagName, 20) ty = fStrCut("【Error】", 20) na = fGetType(Element.getAttribute("NAME"), 26) id = fGetType(Element.getAttribute("ID"), 26) va = fGetType(Element.getAttribute("value"), 30) myText = myText & No & TN & ty & na & id & va & vbCrLf i = i + 1 Else No = fStrCut(CStr(i), 10) TN = fStrCut(Element.tagName, 20) ty = fGetType(Element.getAttribute("Type"), 20) na = fGetType(Element.getAttribute("NAME"), 26) id = fGetType(Element.getAttribute("ID"), 26) va = fGetType(Element.getAttribute("value"), 30) myText = myText & No & TN & ty & na & id & va & vbCrLf i = i + 1 End If Next Else '指定の要素だけ取得する For Each Element In .Document.All.tags(Text3.Text) '取得したデータを表示する為に加工 No = fStrCut(CStr(i), 10) TN = fStrCut(Element.tagName, 20) ty = fGetType(Element.getAttribute("Type"), 20) na = fGetType(Element.getAttribute("NAME"), 26) id = fGetType(Element.getAttribute("ID"), 26) va = fGetType(Element.getAttribute("value"), 30) myText = myText & No & TN & ty & na & id & va & vbCrLf i = i + 1 Next End If End With RichTextBox1.Text = myText End Sub Private Function fStrCut(ByRef CutTxt As String, _ ByVal CutLen As Long) As String '半角・全角の混在する文字列を半角換算文字長で取り出し Dim myLen As Long, SysCodeTxt As String SysCodeTxt = StrConv(CutTxt, vbFromUnicode) '文字列を変換 myLen = LenB(SysCodeTxt) '半角換算のバイト数を取得 If myLen <= CutLen Then '指定の長さより短い場合 fStrCut = CutTxt & Space$(CutLen - myLen) '足りない分はスペースで Else '該当の文字列の方が長い場合、指定のバイトでカットする fStrCut = StrConv(LeftB$(SysCodeTxt, CutLen), vbUnicode) If InStr(fStrCut, vbNullChar) > 0 Then '漢字1バイト目で分断された場合の処理 fStrCut = Left$(fStrCut, InStr(fStrCut, vbNullChar) - 1) & " " End If End If End Function Private Function fGetType(ByVal MyType As Variant, _ ByVal myLen As Integer) As String '取得したデータの検査と表示する為の文字列の加工 Dim st As String If Len(MyType) = 0 Or IsNull(MyType) Then fGetType = String$(myLen, " ") Else '取得したデータを指定の文字数にカットする fGetType = fStrCut(CStr(MyType), myLen) End If End Function Private Sub IE_OnQuit() 'ユーザーがIEを閉じた場合 Set IE = Nothing Command2.Enabled = False Command3.Enabled = False Command4.Enabled = False End Sub Private Sub Form_Unload(Cancel As Integer) 'IE が起動中なら閉じる If Not IE Is Nothing Then IE.Quit Set IE = Nothing End If End Sub 上記、実行結果及び使用コントールと配置図 |
上記は、Yahoo!メールのログイン画面の要素を取得した場面です。 これで、アクセスしたい要素がどのようになっているか調べる事ができます。 タグ名を指定すれば、そのタグだけが取得できます。 但し、サイトの作りによっては、エラーが発生してうまく取得できない要素が含まれている場合がありますので、その場合は、エラー処理を追加願います。 |
2.上記プログラム使用上の留意点 |
このように要素を取得するには、Documentプロパティへの読み込みが完了してからでないと取得する事ができません。 従って、以前は、この読み込み完了を取得するのに下記のようなコードが多く使用されていましたが、これにはいくつかの問題があります。 Do While IE.ReadyState <> READYSTATE_COMPLETE DoEvents Sleep 50 Loop 一番の問題は、これでは読み込み完了を確実に取得できない点にあります。例えば、私のサイトのトップページを読み込んだ場合、[ http://hanatyan.sakura.ne.jp/menu.htm ]と[ http://hanatyan.sakura.ne.jp/top.htm ]と[ http://hanatyan.sakura.ne.jp/ ]が同時(同じ時に順次複数のページが読み込(表示)まれる)に読み込まれます。 従って、一番最初に読み込まれた時に上記のコードでは通過してしまい、目的のページが表示される前に次のコードが実行されエラーが発生したりします。 この他、ブランクのページが読み込まれたり、広告のページが同時に読み込まれたりもしますし、サーバーの状態や通信状態等でも影響を受けやすくエラーの発生の元になります。 又、VBは、イベント駆動型の言語なので、イベントで処理するのが望ましい、例えば、キーボードからのキー入力に対して上記のような待機処理でキー入力の有無を判断しませんよね。 それと、指定時間待つ、待機関数のところでも解説しておりましたが、Sleep 関数やDoEvents の多用に対する問題等もあり、ページ遷移の完了を待つのであれば、NavigateComplete2 イベントを Documentプロパティへの読み込み完了を待つのなら、DocumentComplete イベントで取得するようにしましょう。 (斯く言う私も、WEB上の多くのサンプルを習って最近まで使っておりました。) VB上から、IE(InternetExplorer) のイベントを取得するには、参照設定しただけでは取得する事ができません。 下記のように、WithEvents キーワード を使って宣言すると IE のイベントを取得する(拾う)事ができます。 Private WithEvents IE As SHDocVw.InternetExplorer 又、DocumentComplete イベントでは、下記のように取得したい Document が表示されている URL かどうかを調べるようにすればより確実に判断ができます。(他のサンプルでの使用例も参考にして下さい。) Private Sub IE_DocumentComplete(ByVal pDisp As Object, URL As Variant) Debug.Print "[ " & URL & " ]" '同時にどのようなものが表示されるか確認して下さい。 If CStr(URL) <> myURL Then '指定のURL以外は除外する(広告のページやフレーム等が表示されるので) Exit Sub End If Debug.Print でどのようなページが同時に表示されているのかも調べておくのもいいかと思います。 |
3.要素を取得してのその活用例(Yahoo メールへのログイン) |
今回の場合は、ID が付けられているので、ID 属性は、その要素の一意識別子なので同じIDで複数ないのでこれで特定できます。 Private Sub Command3_Click() IE.Document.getElementById("username").Value = "myID" IE.Document.getElementById("passwd").Value = "myPasswd" IE.Document.getElementById(".save").Click End Sub 同様に、Name で特定できるならば、下記のようにしても同じ事です。 IE.Document.getElementsByName("login").Item(0).Value = "myID" IE.Document.getElementsByName("passwd").Item(0).Value = "myPasswd" IE.Document.Forms(0).submit 又、下記のようにすることもできます。 Private Sub Command4_Click() With IE .Document.Forms(0).Elements("login").Value = "myID" .Document.Forms(0).Elements("passwd").Value = "myPasswd" 'IDとパスワードを記憶用のチェックボックスにチェックを入れる If .Document.Forms(0).Elements(".persistent").Checked = False Then .Document.Forms(0).Elements(".persistent").Click End If 'ログインボタンをクリック .Document.Forms(0).submit End With End Sub 下記でも同様に実行できます。 Private Sub Command5_Click() IE.Document.All.tags("INPUT").Item(30).Value = "myID" IE.Document.All.tags("INPUT").Item(31).Value = "myPasswd" IE.Document.Forms(0).submit End Sub |
上記の要素の取得で、要素名とかIDで、 基本的には、ID とか Name とか ボタンとかリンクの所に書かれている文字等でどの要素かを特定して、その要素に対して操作する事になります。 従って、書かれている内容によって識別の方法が違うし操作も変わってきます。 出来るだけ、変更されても影響を受けにくくて操作が簡単な方法を選んで下さい。 ID → name → 表面等に書かれている文字 → 複数の条件の組み合わせ → 取得順 のように。 但し、サイトのレイアウトや記入項目等変更された場合は、当然のことながらこちらも同様に変更しないと操作できません。 |
4. |
5. |
6. |
検索キーワード及びサンプルコードの別名(機能名) |