MacでPyAutoGUIを利用するにあたって注意すべき点
環境
macOS Big Sur 11.2.2
Python 3.8.6
PyautoGUI 0.9.52
デフォルトシェル zsh
撮影が上手く出来ない
- スクリーンショットが上手く撮れない
- confidenceを下げてもlocateCenterOnScreenが反応しなかったり、NullやNotImageExceptionが起きる。(画像を使った機能は内部でスクリーンショットを利用している)
#例えばJupyterLabやブラウザを立ち上げた状態でスクリーンショットを撮って保存する
import pyautogui
sc = pyautogui.screenshot("fullscreen.png")
真っ新なデスクトップが表示されており、思ったようなスクリーンショットが出来ていない。
解決策
- システムと環境設定を開く
- セキュリティとプライバシーをクリック
- プライバシータブを選択
- 画面収録を選択
- 鍵を外してターミナルにチェック、ターミナルの再起動
moveToなどのマウス操作が機能しない
import pyautogui
pyautogui.moveTo(1,1)
print(pyautogui.position())
#実行すると、
#Point(x=230, y=326)
#といった具合に全く動いていない
解決策
- システムと環境設定を開く
- セキュリティとプライバシーをクリック
- プライバシータブを選択
- アクセシビリティを選択
- 鍵を外してターミナルとAEServer(OSのバージョンによって名称が異なるかも。)にチェックを入れて、再起動
画像認識の場所がどうもおかしい
import pyautogui
pos = pyautogui.locateCenterOnScreen('youtube.png', grayscale=False,confidence=0.8)
print(pos)
pyautogui.moveTo(pos.x,pos.y)
print(pyautogui.position())
#座標だけ見ると正しい位置に移動した様に見える
#Point(x=394, y=234)
#Point(x=394, y=234)
#しかし明らかにカーソルはターゲットとズレている。
#一致した箇所のスクリーンを撮影すると、認識した場所とカーソルがズレていることがわかりやすい。
sc = pyautogui.screenshot(region(pos.left,pos.top,pos.width,pos.height))
sc.save('deteceObj.png')
解決策
x,yともに2で割ると上手くいく
import pyautogui
pos = pyautogui.locateCenterOnScreen('target.png', grayscale=False,confidence=0.8)
print(pos)
pyautogui.moveTo(pos.x/2,pos.y/2)
print(pyautogui.position())
#座標だけ見るとズレている様だが、実際には認識した場所にカーソルがある。
#Point(x=337, y=230)
#Point(x=168, y=115)
locateCenterOnScreeなど認識が上手く出来ない
解決策
オプションの変更や、RGB値でのマッチにする
# 識別精度を調整する opencv-pythongが必要
pos1 = pyautogui.locateCenterOnScreen('target.png',confidence=0.8)
#グレースケールでの検索(高速になるらしいが、個人的には違いがわからない。。)
pos2 = pyautogui.locateOnScreen('traget.png', grayscale=True)
#探索範囲を絞る この場合、(1,1)から幅400px、高さ200pxのエリアで検索する
pos3 = pyautogui.locateOnScreen('taget.png', region=(1, 1, 400, 200))
# RGBマッチにしてみる この場合、(100,100)が赤色(255, 0, 0)かどうかのtrue/falseを返す
# オプションでマッチする範囲を広げられる
ismatch = pyautogui.pixelMatchesColor(100, 100, (255, 0, 0))
ismatch = pyautogui.pixelMatchesColor(100, 100, (255, 0, 0),tolerance=30)
cronを利用するとFileNotFoundErrorになり実行できない
なお、そもそもcronが利用できない場合は、システム環境設定→セキュリティとプライバシー→フルディスクアクセス
にcronがあるか確認する。cronがない場合は、鍵を外して+マークから/usr/sbin/cronを追加し、チェックマークを入れて鍵を掛けておく。
次の例では毎日21時に上述のshoto.pyを実行し、ログを書き出す。
(cronの書き方についてはこちらなどを参考に)
なお、pythonのパスはwhich python
とターミナル入力すれば取得できる。
0 21 * * * pythonのフルパス /Users/ユーザーネーム/Desktop/shoto.py > /Users/ユーザーネーム/Desktop/err.log 2>&1
実行するとerr.logに以下の様な文章が書き出された。
(ログに何も書き出されていない場合はターミナルからmailを実行すると何かしらログを確認できるかも)
Traceback (most recent call last):
File "/Users/ユーザーネーム/shoto.py", line 2, in <module>
sc = pyautogui.screenshot("fullscreen.png")
File "/Users/ユーザーネーム/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pyscreeze/__init__.py", line 446, in _screenshot_osx
subprocess.call(['screencapture', '-x', tmpFilename])
File "/Users/ユーザーネーム/.pyenv/versions/3.8.6/lib/python3.8/subprocess.py", line 340, in call
with Popen(*popenargs, **kwargs) as p:
File "/Users/ユーザーネーム/.pyenv/versions/3.8.6/lib/python3.8/subprocess.py", line 854, in __init__
self._execute_child(args, executable, preexec_fn, close_fds,
File "/Users/ユーザーネーム/.pyenv/versions/3.8.6/lib/python3.8/subprocess.py", line 1702, in _execute_child
raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'screencapture'
解決策1
内部(私の場合は/Users/ユーザーネーム/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pyscreeze/__init__.py)で呼び出されるscreencaptureは/usr/sbinにあるが、cronの環境変数は/usr/binと/binのみの為に実行出来ない模様。
そこで、cronの環境変数に/usr/sbinを追加して実行する。
また、cronが実行されるのはホームディレクトリだが、実際に実行しているshoto.pyはホームディレクトリでは無いので困ることがある。
shoto.pyの場合、fullscreen.pngがshoto.pyと同じフォルダではなく、ホームディレクトリに保存される。絶対pathで保存先を指定すれば回避できるが、他にも困ることがありそうなのでついでに変更する。os.chdir()を使ってPython側で変更しても上手くいくと思う。
PATH=/usr/sbin:/usr/bin:/bin
0 21 * * * cd /Users/ユーザー名/Desktop && pythonのフルパス shoto.py > err.txt 2>&1
解決策2
cronでPythonを直接実行せず、シェルスクリプトを実行する方法もある。
この場合も解決策1と同様に/usr/sbinを追加する必要がある。
#!/bin/zsh
PATH=/usr/sbin:$PATH
cd /Users/ユーザー名/Desktop/scr
pythonのフルパス shoto.py
crontabの記述
0 21 * * * zsh /Users/ユーザー名/Desktop/shoto.sh > /Users/ユーザー名/Desktop/err.txt 2>&1
cronを利用すると撮影が出来ない
cronを利用しないと実行できるが、cronを利用すると上述の「撮影が出来ない」と同じ症状になる。
解決策
- システムと環境設定を開く
- セキュリティとプライバシーをクリック
- プライバシーをクリック
- 画面収録をクリック
- 鍵を外して+ボタン/usr/sbin/cronを追加し、チェックマークを入れて鍵を閉じる
(「crontabを利用するとFileNotFoundErrorになり実行できない」解決策2、のようにシェルを利用している場合は代わりに/bin/zshを追加する)
参考
MacBook ProでPyAutoGUIの座標が正しく取れない?
備忘Lock!! crontabの利用法
cronの環境変数について
Unable to execute a python script via crontab, but can execute it manually. What gives?