k01ken’s b10g

He110 W0r1d!

PythonでPyAutoGUIを利用してみる

開発環境は、Windows 10 Pro + Python 3.7.6。

ちょっとした自動化プログラムを作りたくて、PyAutoGUIを使ってみることにしました。Win32 APIに悪戦苦闘して、作っていたのが、バカらしくなるぐらい、簡単に作れます。びっくりしました。なお、開発者のGitHubによりますと、Windows上では、内部でWin32 APIを用いているようです。

まずは、インストールから

pip install pyautogui


■現在のマウスカーソル位置を取得する

# -*- coding: utf-8 -*-

import pyautogui as pag

x,y = pag.position()
print(x,y)

検索エンジンの検索窓に、クリップボードにあるキーワードを貼り付ける

# -*- coding: utf-8 -*-

import pyautogui as pag

# 上記のコードで取得したマウスカーソルの位置を指定し、位置を移動
pag.moveTo(596,503)

# その位置でクリック
pag.click()

# その位置で、Ctrl + Vを押して、クリップボードにあるデータを貼り付ける
pag.hotkey('ctrl','v')

# その位置で、Enterキーを押す
pag.press('enter')

次の動作をする際にプログラムなどの起動が遅くて、一定時間待たなくてはいけないことが、よくあるんですが、毎回、決まった時間、待つわけじゃないので、どれくらいの秒数待てばいいのか判断に迷います。その際は、次の動作をする際に、必ず、表示されている部分の画像を事前に保存(WindowsだったらSnipping Toolを用いて)しておいて、その画像を、locateCenterOnScreen内に指定して、whileループを用いて、出現するまで待機することができます。出現した場合、その画像がある位置の中心の座標が返ります。例えば、ボタン部分の画像を指定しておくことで、その部分が表示された時に、そのボタン部分に移動し、その後に、click()メソッドを起動するような流れになります。

ただ、基本的なルールとして押さえてもらいたいのが、この方法を多用してしまうと時間を食ってしまい、高速な自動化のメリットが低下してしまいます。そこで、新しいウィンドウが表示される際に1回だけやって、ウィンドウが変更されない限りは、moveRelメソッドを利用して相対的に移動してclickメソッドなどを利用することで、高速な自動化のメリットを享受できると思います。

# -*- coding: utf-8 -*-
import pyautogui as pag
import time

while pag.locateCenterOnScreen('button.png') == None:
  time.sleep(1)
x,y = pag,locateCenterOnScreen('button.png')
pag.moveTo(x,y)
pag.click()

基本的には、これを用いることで、位置が多少ずれたとしても、融通が効くのが便利です。
また、自動化の途中で、ウインドウなどが手前に表示されない場合は、手動で、手前にすると、自動で、そこから再開してくれます。

指定のデータをクリップボードに入れて貼り付けたい場合は、pyperclipモジュールをインストールしましょう。

pip install pyperclip
# -*- coding: utf-8 -*-

import pyautogui as pag
import pyperclip
pyperclip.copy("test")
pag.hotkey('ctrl', 'v')

次に動作するウィンドウが裏側に入って、locateCenterOnScreenが適用できない場合に、強制的に、そのウィンドウを、手前にする方法を教えます。まず、win32guiモジュールをインストールします。自分の場合は、インストールした途中に、一部、エラーになったのですが、importで読みこめました。

pip install win32gui

次に、ウィンドウのタイトルを取得する方法を教えます。すでに、知っている場合は、別に飛ばして構いません。
そのまま実行すると、コマンドプロンプトのウィンドウのタイトルが表示されるので、timeモジュールのsleep関数で数秒間遅延してその間に、取得したいウィンドウを手前に持ってきてください。

import win32gui
import time

time.sleep(3)
print(win32gui.GetWindowText(win32gui.GetForegroundWindow())

取得した後は、次に、そのタイトルを基に、アクティブなウィンドウに切り替えます。

import win32gui

handle = win32gui.FindWindow(None, "切り替えたいウィンドウのウィンドウ名")
win32gui.SetForegroundWindow(handle)

これを実行すると、切り替わったと思います。

実際に、業務で使ってみて問題に感じたことは、マウスの位置を移動して、クリックするまでの間に、マウス自体に手がちょっと当たってしまって、そのまま次の動作に進めないみたいなパターンや、動作スピードが速すぎて、クリックやキーを入力してもズレて動作しないパターンがありました。あとは、moveRelで、マウスを移動する量をいちいち調節するのが面倒というパターンも。
その対策としては、1番目の場合は、上記の方法を行い、2番目の場合は、time.sleepを用いて、0.5秒ぐらい待ってから、動作させてみたら、うまく意図通りに動作してくれました。3番目の場合は、何か独自の関数を作ろうと計画しています。


■参考リンク
Welcome to PyAutoGUI’s documentation! — PyAutoGUI documentation
GitHub - asweigart/pyautogui: A cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.
【Python】PyAutoGuiの画像認識で人間の操作を自動化(RPA)する – 株式会社ライトコード