このページではコンピュータの自動化について記す。 なお、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 メソッドも使用できる。