2017年7月15日土曜日

Nashornを使ってJavaScriptを書いてSelenium (ChromeDriver) を動かす。

はじめに

開発環境ではない環境で、ちょっとしたブラウザ操作を自動化するのに使った方法について書く。

具体的には、Nashorn (Java SE 8で追加されたJavaScriptエンジン。Rhinoの後継) を使い、JavaScriptを書いてSelenium Standalone Serverを呼び出し、ChromeDriverでChromeを自動操作する方法。

「Selenium Standalone ServerはJarなのだから、素直にJavaから呼んだら?」とか、「JavaScriptで書くならSelenium Client & WebDriver Language BindingsのJavaScript (node)を使うのが自然では?」とも思うのも、ごもっとも。自分もそう思う。

それでもこの方法を調べたのは、環境準備が楽だから。JREさえインストールされていれば、あとはSeleniumをダウンロードするだけ。Eclipse, JDK, node.jsどれも必要ない。

「もうすぐjshellを含むJava SE 9がリリースされてJavaをスクリプトとして実行できるようになるだろうに、何をやっているんだ」という気もしているけれど、Java SE 8環境ですぐに動かしたかったので(※2017/10/21追記: JShellでも動かしてみた)。

環境と準備

環境は以下の通り。
  • OS: Windows 10 (64bit)
  • JRE: 8
  • Selenium Standalone Server: 3.4.0
  • Chrome: 59
  • ChromeDriver: 2.30

SeleniumとChromeDriverの準備作業は以下の通り。JREとChromeはインストール済みとする。

Selenium: DownloadsからSelenium Standalone Serverをダウンロードする。保存先フォルダにパスを通すのは必須ではない。Nashornを起動するときにオプションでクラスパスを指定できる。この記事ではその方法を採用する。

ChromeDriver: Downloads - ChromeDriver - WebDriver for Chromeから、chromedriver_win32.zipをダウンロードして展開する。Windows 64bit用は提供されていないので32bit用を使う。こちらも保存先にパスを通すのは必須ではない。Javaの場合、プロパティに設定できる。このエントリィではその方法を採用する。

サンプルコード

ポイントはJavaクラスへのアクセス。標準JavaパッケージのクラスにアクセスするにはFQCNを使う。それ以外のクラス(ここではorg.openqa.seleniumパッケージのクラス)にアクセスするには、Java.type('FQCN')を使う。
// nashorn-selenium.js

// グローバル変数/関数を作らないため即時関数呼び出し。
// 『メンテナブルJavaScript』の「6.4 0-グローバルのアプローチ」参照。
// この使い方の場合、ここまでする必要もないかもしれないけれど一応。
(function() {
  var ChromeDriver, By;
  var pathToChromeDriver, driver, searchBox;

  // Javaのimport相当。
  ChromeDriver = Java.type("org.openqa.selenium.chrome.ChromeDriver");
  By = Java.type("org.openqa.selenium.By");

  // chromedriver.exeへのパスをプロパティに設定。
  // chromedriver.exeが環境変数PATHに指定しているフォルダにあるなら省略できる。
  pathToChromeDriver = 'C:\\\\path\\to\\chromedriver.exe';
  java.lang.System.setProperty('webdriver.chrome.driver', pathToChromeDriver);

  // 実行内容は、
  //   Getting started - ChromeDriver - WebDriver for Chrome
  //   https://sites.google.com/a/chromium.org/chromedriver/getting-started
  // と同じ。
  // Chromeを起動して、Googleで"ChromeDriver"を検索して、Chromeを終了する。
  driver = new ChromeDriver();
  driver.get('http://www.google.com/xhtml');
  java.lang.Thread.sleep(5000);
  searchBox = driver.findElement(By.name('q'));
  searchBox.sendKeys('ChromeDriver');
  searchBox.submit();
  java.lang.Thread.sleep(5000);
  driver.quit();
}());

実行方法

コマンドプロンプトからjjs (nashornを起動するツール) を実行する。その際、-cpオプションでSelenium Standalone Serverをクラスパスに追加しておく。
> jjs -cp "C:\path\to\selenium-server-standalone-3.4.0.jar" nashorn-selenium.js

感想

もろもろの補完が効かないから、スクリプトを書くのが疲れる。けれど、IDE入れるなら環境を整えて、Javaから動かせばよいので、どちらの手間を惜しむかか。

References