このページではコンピュータの自動化について記す。 なお、WEB アプリケーションのスクレーピングなど、関連する話題は下記にある。
コンピュータそのものは自動化のためにあるものだが、対話式に画面で操作しなければならないアプリケーションは、 長らく自動化の対象から外れていた。しかし、コンピュータ技術が進歩し、特に画像を認識する機能が充実してきたことから、 画面を対象に今まで人間が能動的に指示してきた作業もコンピュータができるようになってきた。 最近(私の中では 2018 年ごろ)、ロボティック・プロセス・オートメーションということばを耳にするようになった。 英語では RPA(Robotic Process Automation)という。RPA というと、企業が専用の有償プログラムを使って取り組むイメージが私にはある。 このページでは一個人が RPA もどきを無償のプログラムで使ってできることを考える。
自動化する対象はグラフィカル・ユーザー・インターフェース( GUI )のあるプログラムである。GUI には大きく分けて WEB ブラウザを使うものと使わないものがある。 そこで、自動化を行うツールも、ブラウザに特化せず GUI のあるプログラムであれば使えるものと、ブラウザに特化したものとがある。以下、前者を GUI 自動化、 後者をブラウザ自動化と呼ぶ。ブラウザ自動化には Selenium というツール・ライブラリ群が知られている。また、Node.js を使う Puppeteer というライブラリもある。これらについては、追って準備する予定である。 以下は、GUI 自動化について述べる。
GUI 自動化を行なうツール群として、Python をプログラム言語として使う PyAutoGUI や PyWinAuto がある。両者の違いは、PyAutoGUI がマウスや画面を主体としているのに対し、 PyWinAuto はウィンドウの構成部品をテキストベースで分解して扱うという特徴がある。以下、PyAutoGUI について述べる。
次の conda コマンドでインストールする(https://anaconda.org/conda-forge/pyautogui)
conda install -c conda-forge pyautogui
私の環境(Windows 11 Home Edition)では上記でインストールできた。
Screenshot Functions (pyautogui.readthedocs.io) などを参考にした。
以下は Excel の VBA で Internet Explorer の操作をある程度自動化できるコードを載せる。 2023 年となっては Internet Explorer は古いソフトウェアであり、セキュリティの問題もあるので使ってはいけないが、 資料として載せておく。
Sub IECreateQuit()
Dim objIE As Object
'IE を起動
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
'5秒停止
Call WaitSeconds(5)
'IE終了
objIE.Quit
Set objIE = Nothing
End Sub
Sub GoToKek()
Dim objIE As Object
'IE を起動させる
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
' 高エネルギー加速器研究機構 (kek) に接続
objIE.navigate "https://www.kek.jp/ja/"
'IEを待機
Call IEWait(objIE)
'5秒停止
Call WaitSeconds(5)
'「お問い合わせ」のリンクをクリック
Call IELinkClick(objIE, "お問い合わせ")
'IEを待機
Call IEWait(objIE)
End Sub
Sub GoogleSearch()
Dim objIE As Object
'IE起動
Set objIE = CreateObject("InternetExplorer.Application")
objIE.Visible = True
'Googleに接続
objIE.navigate "https://www.google.com/"
'IEを待機
Call IEWait(objIE)
'検索窓に「VBA」と入力
objIE.document.getElementById("gbqfq").Value = "VBA"
'5秒停止
Call WaitSeconds(5)
'IE終了
objIE.Quit
Set objIE = Nothing
End Sub
既に立ち上げている IE のタイトルバーには "Google" の文字列が入っているものとする。
Sub GoToYahoo()
Dim objIE As Object 'IEを格納する変数(オブジェクト型)
Dim shells As Object '起動中のShellWindow一式を格納する変数
Dim win As Object 'ShellWindowを格納する変数
Dim documentTitle As String 'ドキュメントタイトルの一時格納変数
'起動中の ShellWindow 一式を変数 shells に格納する
Set shells = CreateObject("Shell.Application")
'ShellWindowからウィンドウを1つずつ取得して処理する
For Each win In shells.Windows
'ドキュメントタイトル取得に失敗したときは無視して処理を継続する
On Error Resume Next
documentTitle = win.document.Title
On Error GoTo 0
'タイトルバーに "Google" が含まれるかチェックする
If InStr(documentTitle, "Google") > 0 Then
'変数objIEに取得したwinを格納する
Set objIE = win
'ループを抜ける
Exit For
End If
Next
objIE.Visible = True
'Yahoo! JAPANに接続
objIE.navigate "https://www.yahoo.co.jp/"
End Sub
以上はサブルーチンであった。他に、サブルーチンから呼び出されている関数を掲げる。
Public Function IEWait(ByRef objIE As Object)
Do While objIE.Busy = True Or objIE.readyState <> 4
DoEvents
Loop
End Function
Function WaitSeconds(ByVal second As Integer)
Dim futureTime As Date
futureTime = DateAdd("s", second, Now)
While Now < futureTime
DoEvents
Wend
End Function
Function IELinkClick(ByRef objIE As Object, ByVal anchorText As String)
Dim objLink As Object
For Each objLink In objIE.document.getElementsByTagName("a")
If objLink.innerText = anchorText Then
objIE.navigate objLink.href
Exit For
End If
Next
End Function
' ここでは "INPUT" と書かれているボタンを押す
Public Function IEButtonClick(ByRef objIE As Object, buttonValue As String)
Dim objInput As Object
For Each objInput In objIE.Document.getElementsByTagName("input")
If objInput.Value = buttonValue Then
objInput.Click
Exit For
End If
Next
End Function
' ここでは submit 関数を実行する
Public Function IEFormSubmit(ByRef objIE As Object, ByVal action As String)
Dim objForm As Object
For Each objForm In objIE.Document.getElementsByTagName("form")
If objForm.action = action Then
objForm.submit
Exit For
End If
Next
End Function
次のように select 要素がページに用意されているとする。
value が設定されている場合は、value で指定された値を使い以下のように記述するのがわかりやすい:
objIE.Document.getElementById("frukto").value = "frago"
value が設定されていない場合は、以下のようにするしかない:
objIE.Document.getElementById("frukto").SelectedIndex = "1"
インデックスは 0 から始まるので注意すること。
次のように select 要素がページに用意されているとする。
得意な言語 日本語 エスペラント ドイツ語
'ラジオボタンの「エスペラント」を選択
objIE.Document.getElementsByName("lingvo")(1).Click
'ラジオボタンの「ドイツ語」を選択する
'objIE.Document.getElementsByName("lingvo")(2).Click
objIE.Document.getElementsByName("select1[]")(1).Checked = True
id で指定されていて重複がなければ、getElementById メソッドも使用できる。