GUI自動操作ツール Sikuli を Ubuntu 11.10(Oneiric) にインストール

Sikuli は、デスクトップアプリケーションを自動操作するためのツールで、ボタンの画像をキャプチャしておいて画像認識で操作するという、独特ですが直感的なスクリプト体系が特徴的なツールです。

例を見れば一目瞭然なので、サンプルとして、Chrome の特定のプラグインを無効化するスクリプトを書いてみました。

「スパナのアイコン」→「設定」→「拡張機能」と順にクリックし、特定のアイコンを探して、その右に「有効」となっているチェックボックスがあれば、それをクリックして、最後に設定タブを閉じる。……と、若干複雑な事をさせていますが、それなりに直感的に読めたのではないでしょうか。

今日のエントリは、この sikuli を ubuntu 11.10 (Oneiric) にインストールする作業のメモです。Ubuntu 12.04 のリリースを控えた今のタイミングでは、非常に賞味期限の短い記事になりそうですが、備忘録として書いておきます。

Ubuntu 11.10 での状況

実は、Sikuli も、 Universeリポジトリに入ってますので、 apt でインストールできます。

$ sudo apt-get install sikuli-ide

ところが、このパッケージ、ちょくちょく依存関係がおかしかったり、して動かないことが多いようで……。

私が試した時点では、 Ubuntu の公式リポジトリにある Jython のバージョンが古いせいで動作しない状況でした。 ( この問題は、Launchpad で報告されています → https://bugs.launchpad.net/ubuntu/+source/sikuli/+bug/829757 )

なので、 apt でインストールした上で、新しい Jython を用意する必要があります。

Jython のインストール

まずは Jython 公式ページのダウンロードページ http://www.jython.org/downloads.html から、現時点で安定版の最新バージョンである Jython 2.5.2 の installer をダウンロードし、それを実行しました。

$ java -jar path/to/downloaded/jython_installer-2.5.2.jar

サンプルとかドキュメントは不要なので standalone インストールで良いと思ったのですが、このインストーラも挙動が怪しく、なぜか minimum と standalone が逆になっているかのような挙動を示してくれたので、一番テストされていて無難と思しき standard を最終的には使用しました。

インストール先はどこでもかまいません。私は ~/bin/jython2.5.2/ にしました。

起動スクリプトの調整

sikuli-ide パッケージをインストールし、最新の Jython が用意できたので、あとは起動させてやるだけです。

ですが、残念なことに、sikuli-ide パッケージに同梱されている /usr/bin/sikuli-ide は /usr/share/jython などを静的に指定している起動スクリプトなので、そのままでは起動させることができません。

そこで、このスクリプトを書き換えた自分用の起動スクリプトを作成します。

$ cat /usr/bin/sikuli-ide | sed "s:/usr/share/jython:$HOME/bin/jython2.5.2:; s:/usr/share/java/jython.jar:$HOME/bin/jython2.5.2/jython.jar:" > ~/bin/launch-sikuli-ide
$ chmod +x ~/bin/launch-sikuli-ide 

あとは、このスクリプトを呼んでやれば Sikuli の IDE が起動します。

$ launch-sikuli-ide 

ちなみに、Ubuntu は標準で $HOME/bin/ にパスが通っているので、上記のようにパスを省略して起動できます。ただ、PATHの優先順位は /usr/bin/ などの方が高いので、同じ名前のスクリプトがあるとシステム側の方が起動してしまいますので注意です。

Sikuli スクリプトを書くうえでの tips

ドキュメントは下記の場所に一通り揃っていますので、python が書ける人なら、多少複雑な事でも書き方に困る事は無いでしょう。

Sikuli Documentation

基本的には、 click() を列挙していれば良いだけですし、表示された物によって分岐する場合は exists() を使えばOKです。

exists() してみて見付かったらそれをクリック、ならこんな風に書けます。

if exists(<キャプチャ画像>):
    click(getLastMatch())

ここで注意が必要なポイントが1つあります。
exists() などの画像検索系関数は、マッチする画像が無ければ一定時間(デフォルトでは3秒)、マッチする画像が表示されるのを待つようになっています。そのため、上記の if 文では、マッチする画像が無いと3秒間止まってしまうのです。
表示される候補が複数あってどれかを待つ、など、「画像が見付からない事が多い」場合は、exists() に 2つ目の引数としてタイムアウト時間を渡せば無駄に待たされる事はありません。

wait(<待ち時間 or 表示されるまで待つ画像>)
if exists(<キャプチャ画像a>, 0) or not exists(<キャプチャ画像b>, 0):
    click(getLastMatch())

あと、画像はデフォルトだとかなりいいかげんにマッチングするので、類似度設定は常に高めに調整しておいたほうが良いみたいです。

一方、キーボード操作に対しても1つ罠があります。
文字を入力するには type() 関数を使う、とドキュメントなど各所で書かれていますが、この関数は英字QWERTY配列のキーボードをシミュレートしているので、日本語キーボードの環境で動作させると、記号などが化けます。 (真っ先にはまるのは URL とかメールアドレスを入力する時でしょうか。)

この workaround として、クリップボード経由のコピペをシミュレートする paste() 関数が導入されていますので、記号を含む文字の入力の場合、paste() を使っておいた方が無難でしょう。

といった所で、今日のエントリはここまで。
(もう少し本格的に実用してみたら、この sikuli をデスクトップを占拠させずに使う、というネタで後日、もう1エントリ書くかもしれません。)