PyAutoGUIを使った自動化 -入門編-  〜D&Dやスクロールなどのマウス操作も簡単に〜

## はじめに
PyAutoGUI(PythonのGUI自動化モジュール)を使ってザックリとどのようなことができるのか調べてみました。
PyAutoGUIはSikuliのように画像でマッチングさせて操縦します。
公式ドキュメント：https://pyautogui.readthedocs.io/en/latest/

公式ドキュメントを見ると色々できることはありそうですが、
本記事では個人的に興味があったマウス操作のところを実際にコード書いて見てみようと思います。


## 環境
本記事は以下の環境で動作を確認したものです。

* OS : macOS Mojave (10.14.2)
* ブラウザ : Google Chrome (72.0.3626.109)
* Python : 3.6.3

## OSのセキュリティの設定変更
* 以下の手順でターミナルを追加する
    * システムの環境設定 > セキュリティとプライバシーの設定 > アクセシビリティ > ＋(追加ボタン) > ターミナル
* これをしていないと、PyAutoGUIでマウスの座標は取得できても、カーソルの移動やクリック操作ができません
    * [Pyautogui doesn't seem to work on macOS Mojave](https://github.com/asweigart/pyautogui/issues/247)

## PyAutoGUIのインストール

```
$ pip install pyobjc-core
$ pip install pyobjc
$ pip install pyautogui

## ブラウザを立ち上げてGUIを操作もできるようにするため、
## Seleniumとchromedriverのインストールもしておきます
$ pip install selenium
$ pip install chromedriver-binary
```

## ブラウザに表示されたページをPyAutoGUIで操作してみる
以下のコードでは、ブラウザを起動してページを開くところまでをSeleniumでやって、
その他の操作はPyAutoGUIでしています。
もちろん、Selenium単体でも同様の操作が可能です。
画像ベースなので要素のセレクタを調べたりとかは一切しなくて良いです。

Yahoo!のトップページから週間天気予報を閲覧するコード例に紹介します。


**Yahoo!のトップページ**
![スクリーンショット 2019-02-27 13.00.27.png](https://qiita-image-store.s3.amazonaws.com/0/19778/686c1a7e-c8b6-f08e-c4d2-08f0a6809dee.png)

#### ソースコード

```python
import pyautogui as pyautogui
from selenium import webdriver
import chromedriver_binary

## Yahoo!のトップページを開く
driver = webdriver.Chrome()
driver.maximize_window()
driver.get('https://www.yahoo.co.jp/')

## 「天気・災害」のリンクを開く
x,y = pyautogui.locateCenterOnScreen('weather.png')
pyautogui.moveTo(x, y)
pyautogui.click(x, y)

## 週間予報が表示されるように少し縦にスクロールする
pyautogui.vscroll(-5)

## 範囲を指定して週間予報の部分のスクリーンショットを取得する
screenshot = pyautogui.screenshot(region=(225, 225, 650, 450))
screenshot.save('yahoo_weather.png')

driver.quit()
```

**「天気・災害」のリンクを検出するための画像**
![weather.png](https://qiita-image-store.s3.amazonaws.com/0/19778/dac90437-8d53-792b-5143-150e769c3b25.png)

**取得したスクリーンショット(yahoo_weather.png)**
![yahoo_weather.png](https://qiita-image-store.s3.amazonaws.com/0/19778/41c78e2b-f182-995f-f331-453c790cf700.png)

## デスクトップアプリでマウス操作を試してみる
RICOH THETAの[パソコン用アプリケーション](https://support.theta360.com/ja/download/)(全天球画像をPC上で閲覧できるアプリ)で
以下のマウス操作を試してみました。

* マウスカーソルの移動
* ドラッグ&ドロップ
* クリック
* スクロール

動くものを見ていただいた方がわかりやすいため動画を撮りました。
やっていることはコードに解説を入れています。

![movie.gif](https://qiita-image-store.s3.amazonaws.com/0/19778/3fefec3d-c368-963c-e31f-5e0b1b913afc.gif)


#### ソースコード

```python
import pyautogui as pyautogui
from time import sleep 

# サンプル画像の位置を取得し、マウスカーソルを移動させる
x,y = pyautogui.locateCenterOnScreen('sample.png')
pyautogui.moveTo(x, y)

# ドロップエリアの位置を取得し、ドロップエリアにドラッグ&ドロップ
drop_area_x, drop_area_y = pyautogui.locateCenterOnScreen('drop_area.png')
pyautogui.dragTo(drop_area_x, drop_area_y, 1, button='left')
sleep(1) # 画像がロードされるまで待機

# ドラッグ・スクロール操作で表示された全天球画像のビューを変更
pyautogui.mouseDown(drop_area_x + 300, drop_area_y, button='left') # 左クリック押しっぱなし
pyautogui.dragTo(drop_area_x - 300, drop_area_y, 1, button='left') # 左方向へ回転
sleep(1) # 動きをみやすくするために操作毎に1秒の待機処理を挟む
pyautogui.dragTo(drop_area_x - 300, drop_area_y + 200, 1, button='left') # 上方向へ回転
pyautogui.mouseUp(x, y, button='left') # 左クリック解放
sleep(1)
pyautogui.scroll(10, drop_area_x, drop_area_y) # ズームイン
sleep(1)
pyautogui.scroll(-20, drop_area_x, drop_area_y) # ズームアウト
sleep(1)
```

マウス操作はだいたいできます！ただ、自分でコードを書いていて気付いたことがありました。
検出するために用意する画像を大きくすると検索処理が遅くなるため、特定できる程度に小さい範囲で画像を用意するのをオススメします。
キーボード操作は今回全然触れていないので、次回また書いてみようと思います！

半日、PyAutoGUIで遊んでみての感想です。
自動化のツールとしては導入するハードルが高いわけでもなく、使い勝手が悪いわけでもなさそうなので
活用する場面は結構あるように思います。
前にSikuliを使った自動化について、勉強会で画像認識に結構頑張らないといけないと聞いたことがありますが、認識されなくて困るといったことはありませんでした。