14
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MacでのPyAutoGUIの注意点

Last updated at Posted at 2021-03-04

MacでPyAutoGUIを利用するにあたって注意すべき点

環境

macOS Big Sur 11.2.2
Python 3.8.6
PyautoGUI 0.9.52
デフォルトシェル zsh

撮影が上手く出来ない

  • スクリーンショットが上手く撮れない
  • confidenceを下げてもlocateCenterOnScreenが反応しなかったり、NullやNotImageExceptionが起きる。(画像を使った機能は内部でスクリーンショットを利用している)
shot.py
#例えばJupyterLabやブラウザを立ち上げた状態でスクリーンショットを撮って保存する
import pyautogui
sc = pyautogui.screenshot("fullscreen.png")

test.png
真っ新なデスクトップが表示されており、思ったようなスクリーンショットが出来ていない。

解決策

  1. システムと環境設定を開く
  2. セキュリティとプライバシーをクリック
  3. プライバシータブを選択
  4. 画面収録を選択
  5. 鍵を外してターミナルにチェック、ターミナルの再起動

moveToなどのマウス操作が機能しない

mouse.py
import pyautogui
pyautogui.moveTo(1,1)
print(pyautogui.position())

#実行すると、
#Point(x=230, y=326)
#といった具合に全く動いていない

解決策

  1. システムと環境設定を開く
  2. セキュリティとプライバシーをクリック
  3. プライバシータブを選択
  4. アクセシビリティを選択
  5. 鍵を外してターミナルとAEServer(OSのバージョンによって名称が異なるかも。)にチェックを入れて、再起動

画像認識の場所がどうもおかしい

detec.py
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で割ると上手くいく

detec.py
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値でのマッチにする

chageoption.py
# 識別精度を調整する 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を追加する必要がある。

shoto.sh
#!/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を利用すると上述の「撮影が出来ない」と同じ症状になる。

解決策

  1. システムと環境設定を開く
  2. セキュリティとプライバシーをクリック
  3. プライバシーをクリック
  4. 画面収録をクリック
  5. 鍵を外して+ボタン/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?

14
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?