SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

CoffeeScriptによるモダンなWebアプリケーション開発

CoffeeScriptベストプラクティス集
Node.jsアプリケーション編(2)

CoffeeScriptによるモダンなWebアプリケーション開発 第4回

  • X ポスト
  • このエントリーをはてなブックマークに追加

ヘッドレスブラウザ

 GUI(注2)を持たずプログラムから操作できるブラウザをヘッドレスブラウザと呼びます。通常のブラウザと違って表示ウインドウを持たないためにヘッドレス(頭部を持たない)と呼ばれます。

 PhantomJS(BSDライセンス)はWebKit(注3)をベースとしたヘッドレスブラウザで、JavaScriptのAPIを持ちます。通常のブラウザのようなユーザ操作を再現することができ、Webサイトにアクセスしてフォームを送信したり、ページのキャプチャを取ったりすることができます。またページ内のJavaScriptやCSS、Cookieなども通常のブラウザと同じように扱えます。

 ヘッドレスブラウザは実際のブラウザとほぼ同等に動作するうえ、LinuxサーバなどでGUIのない環境でも実行できます。Webサイトのコードを修正した時にUIや遷移が崩れていないかどうかテストするプログラムを作ったり、スクレイピング(注4)をする際などに便利です。

注2:GUI

 ターミナルではなくマウスで操作できるウインドウなどのインタフェースのこと。Graphical User Interfaceの略。

注3:WebKit

 SafariやChromeなどのブラウザで使われているレイアウトエンジン。

注4:スクレイピング

 Webページから一部の必要なデータだけを取得してプログラムで利用すること。

PhantomJSのインストール

 まず、ヘッドレスブラウザ本体であるPhantomJSをインストールします。

MacまたはLinuxの場合

 PhantomJSのWebサイトからファイルをダウンロードします。

 ダウンロードしたファイル名にstaticと付いている場合は、解凍すると現れるbin/phantomjsを/usr/local/bin/などのPATHが通ったディレクトリにコピーしてインストールは完了です。

 一方、ファイル名にdynamicと付いている場合は、解凍したディレクトリをそのまま任意の場所に移動し、PATHの通ったディレクトリからbin/phantomjsに対してシンボリックリンクを作成します。例えば解凍したディレクトリを/usr/local/phantomjsに置いた場合、

ln -s /usr/local/phantomjs/bin/phantomjs /usr/local/bin/

 と実行すると、/usr/local/bin/phantomjsにシンボリックリンクが作成され、phantomjsコマンドが使えるようになります。

Windowsの場合

 PhantomJSのWebサイトからファイルをダウンロードします。解凍すると現れるphantomjs.exeがPhantomJSのプログラム本体なので、任意の場所に移動してPathを通します。

CasperJSのインストール

 PhantomJS自体はJavaScriptのAPIを持っており、phantomjsコマンドで利用することができます。しかしPhantomJSは基本的なAPIしか持たないため、フォーム送信などの複雑な操作をするのは少し大変な作業となってしまいます。

 そこで、PhantomJSの扱いを簡単にするためCasperJS(MITライセンス)というツールをインストールします。CasperJSはPhantomJSの上で動くツールで、これを使うと複雑な操作を簡単なAPIで実現できます。

MacまたはLinuxの場合

 CasperJSのWebサイトからファイルをダウンロードします。解凍すると現れるディレクトリを任意の場所に配置し、PATHが通ったディレクトリからシンボリックリンクを張ります。例えば解凍したディレクトリを/usr/local/casperjsに置いた場合、

ln -s /usr/local/casperjs/bin/casperjs /usr/local/bin/

と実行すると/usr/local/bin/casperjsにシンボリックリンクが作成されます。実行するときはコマンドラインから

casperjs ファイル名

のように入力します。

Windowsの場合

 CasperJSのWebサイトからファイルをダウンロードします。解凍すると現れるディレクトリ内のbin/casperjsがプログラム本体です。中身はPythonスクリプトなので、コマンドプロンプトから

python bin/casperjs ファイル名

 のように実行できます。Cygwinなどを使えば、casperjs ファイル名で起動できるように環境を設定することも可能です。

Node.jsでは実行不可

 PhantomJSやCasperJSは独自のJavaScriptエンジンを使うため、nodeやcoffeeコマンドで実行することはできません。その代わり、CasperJSやPhantomJSはJavaScriptとCoffeeScriptのいずれのソースファイルも直接実行できます。拡張子が.jsか.coffeeかによって自動的に判断されます。

CasperJSの使い方

 CasperJSのプログラムはリスト17のように記述します。jQueryをscripts/jquery-latest.min.jsに設置してこのプログラムを実行すると、Webページにアクセスしてフォームを送信し、リンクをたどり、CSSを変更してキャプチャを取ります。

リスト17 CasperJSでWebページを操作する
# casperインスタンスを作成する
casper = require('casper').create()

# URLを開く
casper.start 'http://www.yahoo.co.jp/', ->
  # 画面サイズを幅1024px、高さ768pxにセットする
  @viewport 1024, 768

  # ページタイトルが一致することを確認する
  @test.assertTitle 'Yahoo! JAPAN', 'タイトルがYahoo! JAPAN'

  # フォームに値を入力して送信する
  @fill 'form[name="sf1"]', p: '東京 wikipedia', true

# ページがロードされるまで待つ
casper.then ->
  # ページ内にjQueryを読み込む
  @page.injectJs 'scripts/jquery-latest.min.js'

  # ページ内でJavaScriptを実行し、その値を受け取る
  links =  @evaluate ->
    # この部分のコードがページ内で実行される

    # <h3>以下のテキストを収集して配列にして返す
    links = $('h3')
    $(link).text() for link in links

  # 結果を表示する
  for link, i in links
    @echo "#{i+1} - #{link}"

  # URLに特定の文字列が含まれることを確認する
  @test.assertUrlMatch /\?p=東京\+wikipedia/, 'URLに検索文字列が含まれる'

  # DOM要素が存在することを確認する
  @test.assertExists 'div#contents', 'div#contentsが存在'

  # 文字列が存在することを確認する
  @test.assertTextExists '検索結果', '「検索結果」という文字列が存在'

  # CSSセレクタに該当するリンクをクリックする
  @click '#WS2m > ul > li:first-of-type h3 a'

# ページがロードされるまで待つ
casper.then ->
  # URLが一致することを確認する
  @test.assertEquals @getCurrentUrl(),
    'http://ja.wikipedia.org/wiki/東京', 'URLが一致'

  # ページ内でJavaScriptを実行する
  @evaluate ->
    # 配色を変える
    h1 = document.getElementById('firstHeading')
    h1.style.backgroundColor = '#333'
    h1.style.color = '#fff'

  # ページのキャプチャを取りファイルに保存する
  @capture 'wikipedia.png'

# 全体を実行する
casper.run ->
  # すべて完了したらPhantomJSを終了する
  @exit()

 このプログラムはcoffeeコマンドを使わずにcasperjs ファイル名のように実行します。実行すると図1のように結果が表示されます。

図1 リスト17の実行結果
図1 リスト17の実行結果

CasperJSの主なAPI

 CasperJSの主なAPIを紹介します。

基本的な操作

 以下の関数の引数callbackの中では、thisでcasperオブジェクトを参照できます。[ ] で囲まれた引数の指定は任意です。

casper.start(url, [callback])

 Casperをスタートし、urlを開きます。callbackで関数が指定されると、ページがロードされた後で実行されます。casper.start()メソッドの引数を1つも指定しない場合は、Casperのスタートだけが行われます。

casper.open(url, [settings])

 urlを開きます。事前にcasper.start()メソッドが呼ばれている必要があります。POSTリクエストを送る際は、次のようにsettings引数を指定します。dataプロパティには文字列またはオブジェクトを指定できます。オブジェクトを指定すると、=&で組み合わせた文字列となって送信されます。

casper.open 'http://localhost/post',
  method: 'post'
  data:
    query: 'tea'
    count: 100
casper.then(callback)

 ページがロードされた後でcallbackの関数を実行します。

casper.run(callback)

 ステップ全体を実行します。完了後にcallbackの関数が呼ばれます。

casper.exit([status])

 PhantomJSを終了します。statusを指定した場合、その値がプロセスの終了ステータスとなります。

casper.wait(timeout, [callback])

 timeoutで指定されたミリ秒の間一時停止します。callbackを指定すると、再開時に実行されます。

ページ内の操作

casper.viewport(width, height)

 画面の表示サイズを幅widthピクセル、高さheightピクセルにセットします。

casper.getCurrentUrl()

 現在のページのURLを返します。URLデコードされた文字列が戻り値となります。

casper.click(selector)

 CSS3セレクタselectorに該当する要素をクリックします。

casper.fill(selector, values, [submit])

 CSS3セレクタselectorに該当するフォームについて、valuesオブジェクトに指定された値をそれぞれセットします。submittrueを指定するとフォームの送信も行います。

 例えば次のようなHTMLに対して操作する場合を考えます。

<form id="search_form" action="/search" method="get">
  <input type="text" name="query">
  <input type="text" name="count">
  <input type="submit" value="送信">
</form>

 この場合、フォームに値を入力して送信するには次のように記述します。

casper.fill 'form#search',
  query: 'tea'
  count: 100
, true
casper.back()

 1つ前のページに戻ります。

casper.evaluate(fn)

 fnに指定された関数をページ内で実行し、値を返します。

casper.echo(message, [style])

 標準出力にmessageを出力します。styleを指定すると色付きで表示されます。styleには次のうちの一つを指定できます。ERROR, INFO, TRACE, PARAMETER, COMMENT, WARNING, GREEN_BAR, RED_BAR, INFO_BAR。

図2 スタイル付きで出力する
図2 スタイル付きで出力する
casper.debugHTML()

 デバッグ用に現在のページのHTMLを出力します。

casper.capture(filename, [clipRect])

 ページをレンダリングしてfilenameのファイルに保存します。.pngや.jpg、.pdfなど拡張子によって出力フォーマットが変わります。clipRectにオブジェクトを指定すると、部分的に切り取って保存できます。例えば次のように指定すると、上0px、左0pxの位置から幅1024px、高さ768pxの領域が保存されます。

@capture 'page.png',
  top   : 0
  left  : 0
  width : 1024
  height: 768

 ページ内で背景色が決められていない部分の背景は透明になります。デフォルトの背景色を白に設定するにはcasper.evaluate()メソッドを使って次のようにCSSを変更してからキャプチャを取ります。

# 背景色を変更する
casper.evaluate ->
  document.body.style.backgroundColor = 'white'

# キャプチャを取る
casper.capture 'page.png'
casper.page.injectJs(path)

 pathのファイルを外部JavaScriptとしてページ内に読み込みます。ローカルのファイルのみ指定可能で、URLは指定できません。

テスト用メソッド

 以下の各メソッドで最後の引数messageを指定すると、そのメッセージがテスト実行時に表示されます。messageの指定は任意ですが、ここにテストの概要を書いておくとわかりやすくなります。

casper.test.assert(condition, [message])

 conditiontrueであることを確認します。「trueとして解釈できる値」ではなく厳密にtrueである必要があります。

casper.test.assertEquals(testValue, expected, [message])

 testValueexpectedを厳密に比較して等しいことを確認します。

casper.test.assertExists(selector, [message])

 CSS3セレクタselectorに該当する要素が存在することを確認します。

casper.test.assertTextExists(expected, [message])

 ページ内に文字列expectedが出現していることを確認します。

casper.test.assertTitle(expected, [message])

 ページのタイトルがexpectedと一致することを確認します。

casper.test.assertUrlMatch(pattern, [message])

 ページのURLが正規表現patternにマッチすることを確認します。

その他のメソッド

 その他のメソッドはCasperJSのWebサイトを参照してください。

次のページ
Webアプリケーションの開発

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
CoffeeScriptによるモダンなWebアプリケーション開発連載記事一覧

もっと読む

この記事の著者

飯塚 直(イイヅカ ナオ)

1984年東京都生まれ。 高校時代に趣味でPerlやJavaを使ってプログラミングを始める。 慶応大学湘南藤沢キャンパス卒業後、共同通信社にてニュースサイトの開発などを担当。 その後、面白法人カヤックにてソーシャルゲームの開発などを手がける。 2012年現在、カヤックを退社し個人として活動し...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6528 2012/05/01 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング