SikuliXは、グラフィカルユーザーインターフェイス(GUI)の自動化と操作を目的としたソフトウェアツールです。その特徴は「視覚ベースのスクリプティング」で、画面上の特定の画像(ボタン、アイコンなど)を検出し、それに対してマウスクリックやキーボード入力などのアクションを実行することができます。
一方、scrcpyは、Androidデバイスの画面をPC上にミラーリングするアプリケーションです。USBまたはTCP/IP経由で接続することが可能で、低遅延・高画質が特徴です。scrcpyはコマンドラインで実行するアプリケーションですが、guiscrcpyを使えばGUIからscrcpyを起動することができます。
SikuliXとscrcpy/guiscrcpyを組み合わせることで、Android端末を自動操作することができます。毎日決まった時間にゲームアプリを起動し、ログインボーナスを受け取る、といったことも可能です。
しかし、アプリによってはSikuliXのスクリプトでclick関数を実行しても、うまくクリックされたり、クリックされなかったりすることがあります。同じアプリでも、ほとんど問題が出ないページと、クリックミスが頻発するページがあります。とくに、ゲームアプリで顕著に発生します。
どうも、SikuliXのclick関数だと、あまりにクリック時間(ボダンを押して離すまでの時間)が短すぎてアプリが反応しないことがあるようです。そこで、以下ようにSettings.ClickDelayを設定してクリック時間を長くしてみました。
Settings.ClickDelay = 0.2
click(loc) # locは座標
Settings.ClickDelayに設定できるのは1.0未満で、上の例では0.2秒ディレイがかかります。clickが実行されると0に戻るので、clickする度に設定する必要がある点には注意が必要です。
これで、クリックに失敗することは少なくなったのですが、私の環境ではClickDelayを長くしても失敗することがありました。そこで、以下のような「tap」関数を作り、click()関数は使わず、mouseDown(Button.LEFT)とmouseUp(Button.LEFT)で行うようにしたところ、失敗は無くなりました。
def tap(loc, hold_duration=0.1):
mouseMove(loc)
mouseDown(Button.LEFT)
time.sleep(hold_duration)
mouseUp(Button.LEFT)
押し下げたまま保持する時間はデフォルトで0.1秒ですが、第2引数で指定することもできます。
さらに、「画像を見つけてクリック(タップ)する」という処理もよく行うので、以下の関数tap_imageも作成して使っています。
def tap_image(image_path, region=Screen(), hold_duration=0.1):
try:
target = region.find(image_path)
target_center = target.getCenter()
mouseMove(target_center)
mouseDown(Button.LEFT)
time.sleep(hold_duration)
mouseUp(Button.LEFT)
except FindFailed as e:
print("画像が見つかりませんでした")
print("エラーメッセージ: " + str(e))
return False
except Exception as e:
print("例外が発生しました")
print("エラーメッセージ: " + str(e))
return False
return True
第1引数にキャプチャした画像を指定します。第2引数には画像を探すRegion(領域)を指定できます。無指定だと画面全体から探しますが、余計な時間がかかる上、誤検知して別の部分をクリックしてしまう可能性も上がるので、できるだけ指定するようにしています。第3引数はtap関数と同様、クリックしてから離すまでの時間です。
これらの関数を使うことで、スマホゲームなどの巡回も、完璧とは言えないまでも安定して動くようになりました。同じような問題に困っている人の参考になれば幸いです。
コメント