IE操作のためのクラスを作った
クラスにしてしまったのでぶちまけておく
職場のクソWebアプリの攻略の過程で色んなメソッドを作ったので、無駄にクラス化しておいた。
思いつきを行き当たりばったりで形にしただけなので、ツッコミどころはたくさんあると思う。
複数インスタンスを作るシチュエーションも思い浮かばないので、もしかしたらAttribute VB_PredeclaredId
をTrue
にしてもいいかもしれない。
いちいち手入れするのもめんどくさいので、ソースコードをそのままぶちまけておく。
どうせ一般ウケは狙ってないし。(←負け惜しみw)
WebAppクラス
リスト1 クラスモジュール
オブジェクト名を「WebApp
」としています。
Option Explicit Private Declare Function GetTickCount Lib "kernel32" () As Long Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private GotIE_ As InternetExplorer Private CurrentDocument_ As HTMLDocument Public Property Get GotIE() As InternetExplorer Set GotIE = GotIE_ End Property Public Property Get CurrentDocument() As HTMLDocument On Error Resume Next Set CurrentDocument = GotIE_.Document If Err.Number > 0 Then Set CurrentDocument = Nothing On Error GoTo 0 End Property Public Property Get PageHTMLSource() As String Dim ret As String On Error Resume Next ret = Me.getHTMLSource On Error GoTo 0 PageHTMLSource = ret End Property Private Sub Class_Initialize() Set GotIE_ = New InternetExplorer End Sub Private Sub Class_Terminate() Set GotIE_ = Nothing Set CurrentDocument_ = Nothing End Sub Public Sub init(ByVal targetURL As String) '擬似コンストラクタ' With GotIE_ .Visible = True Call .Navigate(targetURL) Do While .Busy Or .ReadyState <> READYSTATE_COMPLETE DoEvents Loop Call waitFor(2000) Set CurrentDocument_ = .Document End With End Sub Public Function getIEByTitle( _ ByVal titleKeyWord As String) As InternetExplorer 'タイトルにキーワードを含むページを表示中のIEを取得するメソッド' Dim shellApp As New Shell Dim shellWin As Object For Each shellWin In shellApp.Windows If shellWin.Name = "Internet Explorer" Then On Error Resume Next If InStr(1, shellWin.Document.Title, titleKeyWord) > 0 Then Set GotIE_ = Nothing Set GotIE_ = shellWin Exit For End If On Error GoTo 0 End If Next If GotIE_ Is Nothing Then Exit Function Set getIEByTitle = GotIE_ Set shellApp = Nothing Set shellWin = Nothing End Function Public Function getIEByURL( _ ByVal targetURLKey As String) As InternetExplorer 'URLのキーワードが一致するページを表示中のIEを取得するメソッド' Dim shellApp As New Shell Dim shellWin As Object For Each shellWin In shellApp.Windows If shellWin.Name = "Internet Explorer" Then On Error Resume Next If InStr(1, shellWin.Document.URL, targetURLKey) > 0 Then Set GotIE_ = shellWin Exit For End If On Error GoTo 0 End If Next If GotIE_ Is Nothing Then Exit Function Set getIEByURL = GotIE_ Set shellApp = Nothing Set shellWin = Nothing End Function Public Function isTargetPage( _ ByVal pageTitleKeyWord As String) As Boolean 'ページタイトルにキーワードを含んでいるか判定するメソッド' isTargetPage = True On Error Resume Next If InStr(1, Me.CurrentDocument.Title, pageTitleKeyWord) > 0 Then _ Exit Function On Error GoTo 0 isTargetPage = False End Function Public Function getElementByTagAndKeyWord( _ ByVal targetTagName As String, _ ByVal targetKeyWord As String) As Object 'タグ名とキーワードを要素内の文字列に持つ要素を取得するメソッド' Dim ret As Object Set ret = Nothing With Me.CurrentDocument Dim targetElement As Object For Each targetElement In .getElementsByTagName(targetTagName) If InStr(1, targetElement.outerHTML, targetKeyWord) > 0 Then Set ret = targetElement Exit For End If Next End With Set getElementByTagAndKeyWord = ret End Function Public Function getHTMLSource() As String '表示中のHTMLドキュメントのソースを取得するメソッド' Dim ret As String ret = "" On Error Resume Next ret = GotIE_.Document.all(0).outerHTML On Error GoTo 0 getHTMLSource = ret End Function Public Sub createSourceHTMLFile(ByVal fileFullName As String) '表示中のページのHTMLソースをファイルとして出力するメソッド' Dim n As Long n = FreeFile(0) Open fileFullName For Output As n Print #n, Me.PageHTMLSource & vbCrLf Close #n End Sub Public Sub Quit() 'IEを終了するメソッド' GotIE_.Quit End Sub Private Sub waitFor(ByVal milliSeconds As Long) '待ち時間設定用メソッド' '内部処理専用' Dim startTime As Long startTime = GetTickCount Do While (GetTickCount - startTime) < milliSeconds DoEvents Call Sleep(1) Loop End Sub
各メソッドの機能は、コード中のコメントをどうぞ。(なげやり)
使ってみる
WebApp
クラスを、次のコードで利用してみる。
リスト2 標準モジュール
Public Sub disposable03() Dim webApp_ As New WebApp With webApp_ '最初のページに移動する' Call .init("http://akashi-keirin.hatenablog.com/entry/2018/12/16/001606") '最初のページのHTMLソースを出力する' Call .createSourceHTMLFile(ThisWorkbook.Path & "\「マーカ部分を……」_src.html") '「検索」ボックスに「ち~んw」を入力する' Dim targetTextBox As HTMLInputElement On Error Resume Next Do Err.Clear Set targetTextBox = .getElementByTagAndKeyWord("input", "name=""q""") targetTextBox.Value = "ち~んw" Loop Until Err.Number = 0 '検索実行ボタンをクリックする' Dim targetButton As HTMLInputButtonElement Set targetButton = .getElementByTagAndKeyWord("input", "value=""検索""") targetButton.Click Call WindowsAPI.waitFor(5000) 'ページが取得できているかどうか試行錯誤する' Dim n As Long n = 1 Do DoEvents Call WindowsAPI.waitFor(1000) If n > 2 Then _ Call .getIEByTitle("ち~んw") Debug.Print "Wait " & n & " 回目:" & .CurrentDocument.Title n = n + 1 If n > 5 Then .Quit: Exit Do Loop Until .isTargetPage("ち~んw") End With '移動後のページのHTMLソースを出力する' Call webApp_.createSourceHTMLFile( _ ThisWorkbook.Path & "\「ち~んw」の検索結果_src.html") 'メッセージを表示してすべてを終わらせる' Debug.Print "終了" webApp_.Quit Set webApp_ = Nothing Set targetTextBox = Nothing Set targetButton = Nothing End Sub
それぞれのセクションで何をやっているのかは、コード中のコメントをどうぞ。(なげやり)
おわりに
ひとまず、これだけの機能があれば、うちの職場のクソWebアプリには圧勝できる。