あなたはVBAを使ってInternetExplorer(以下IE)を操作しようとしています。そのコンテンツが表示されている部分のソース右クリックで確認し、プログラムを組みました。さぁ操作しよう!
・・・と思ったら動かない。しかもソースを表示させてみるとさっき右クリックで確認したソースと違う・・・なんてことに遭遇したことはありませんか?
もしかしたらそのサイトは”(インライン)フレーム構造”になっているのかもしれません。今回はこの”フレーム”というものがどの様なものか、どの様にして操作すれば良いかをご紹介します。
はじめに
つい最近ebayの操作に関する仕事を受けたのですが、ebayの商品ページは一部がインラインフレーム構造になっていました。
久しぶりだったので「何であの部分のソースが見えないんだっけ」と少し悩みましたが、今後のための備忘録的な意味も込めて書いていきます。まずは基本的な”フレーム構造”の操作から。
”インラインフレーム”については次回の記事で紹介致します。
処理は至ってシンプルなので、すぐに実装できるはずです。
フレーム構造とは?
①
上記の様な構造になっているページを見たことはありませんか?
A側にメニューなどの項目が表示されており、項目をクリックするとB側のページが切り替わるといったページです。
この場合、A、Bそれぞれの位置で「右クリック」⇒「ソースの表示」を行うと、それぞれ異なるソースが表示されると思います。これは以下の様に、
「A.html」、「B.html」という別々のページが存在しているためです。”フレーム”と呼ばれる仕組みを使うことで、一つのページに複数のhtmlファイルのページを表示させることができます。そして実はもう一つ、これらのページを繋げて表示させるために、
「C.html」というページも存在しています。
VBAで上図①のページを取得した際にdocumentの内容を見ると、この「C.html」のソースが確認できるはずです。その他にもIE上で「表示」⇒「ソース」、「Ctrl」+「U」でも確認することができます。
サンプルとして以下の様なページを用意致しました。
https://rabbitfoot.xyz/sample/frame-c.html(新しいタブで開きます)
上記サイトの左側、右側で右クリック。「Ctrl」+「U」でC.htmlのページの確認等を行ってみましょう。
<FRAMESET cols="200,*" border=0> <FRAME SRC="frame-a.html" NAME="pageleft"> <FRAME SRC="frame-b.html" NAME="pageright"> </FRAMESET>
<FRAMESET>が記述されている部分がフレームの指定箇所となります。
各フレームの要素を取得する
では本題へ。
先ほど開いたサンプルのページから「frame-a.html(A)」、「frame-b.html(B)」のドキュメントタイトルを取得してみましょう。
※参照設定が必要になりますので、こちらの記事をご確認下さい(新規タブで開きます)
Option Explicit Sub main() Dim objIE As InternetExplorer Dim objFrame As Object Set objIE = getTargetUrlIE("https://rabbitfoot.xyz/sample/frame-c.html") Set objFrame = objIE.document.frames Debug.Print objFrame(0).document.title Debug.Print objFrame(1).document.title End Sub '指定したURLのサイトを返す Function getTargetUrlIE(url As String) As InternetExplorer Dim objIE As InternetExplorer 'IE格納 Dim objSh As Object 'shellオブジェクト格納 Dim objWindow As Object 'ウィンドウを格納 Dim sWindowName As String 'ウィンドウタイトルを格納 Set objSh = CreateObject("Shell.Application") For Each objWindow In objSh.Windows On Error Resume Next sWindowName = "" sWindowName = objWindow.FullName On Error GoTo 0 'IEウィンドウかどうかの判定 If LCase(Right(sWindowName, 12)) = "iexplore.exe" Then 'URLが指定のものかどうかを判定 If InStr(objWindow.LocationURL, url) > 0 Then Set objIE = objWindow Exit For End If End If Next '目的のIEが開かれていない場合は作成する If objIE Is Nothing Then Set objIE = CreateObject("InternetExplorer.Application") objIE.Visible = True objIE.Navigate2 url Do While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE DoEvents Loop End If Set getTargetUrlIE = objIE End Function
上記のソースをそのまま実行してみて下さい。イミディエイトウィンドウに「メニュー」、「フレームのトップ」と出力されれば成功です。
「objIE.document.frames」でフレームのオブジェクトを取得することができます。予め使用されているフレームの数や位置が分かっているのであれば、サンプルの様に「objFrame(0).document.title」と指定するだけでそのフレーム内の要素に簡単にアクセスすることができます。(添え字の開始は0から始まります)
何番目のフレームにデータが存在するか分からない場合は、for分等を用いてフレームの内容を一つずつ確認していく処理に置き換えれば問題ありません。
forを用いたサンプル
Sub main() Dim objIE As InternetExplorer Dim objFrame As Object Dim iFrameCnt As Integer Set objIE = getTargetUrlIE("https://rabbitfoot.xyz/sample/frame-c.html") Set objFrame = objIE.document.frames For iFrameCnt = 0 To objFrame.length - 1 Debug.Print objFrame(iFrameCnt).document.title Next End Sub
ちなみに”frame”のオブジェクトは必ず一度変数に格納する様にしましょう。
横着をして「objIE.document.frames(0).document.title」と記述するとエラーになります。
フレーム構造となっているサイトの操作方法は以上です。
次回はインラインフレーム構造になっている場合について解説します。