hitode909の日記

趣味はマリンスポーツですの日記です

Phantom.JS 練習 メモ

昨日ちょっとPhantom.JSの練習した.

Phantom.JS

PhantomJS: Headless WebKit with JavaScript API

PhantomJS is a headless WebKit with JavaScript API.

インストール

brew install phantomjs

Qt4が必要でインストールに時間かかる

実行

phantomjs a.js とか phantomjs a.coffee で実行
CoffeeScript実行できる
ただし,コンパイルできないときにどこが悪いかとかは教えてくれない

phantom

グローバルにphantomというオブジェクトがある
phantom.exitとか phantom.argsとか

console.log

console.logでコンソールに出力できる

ページ開く

WebPage#openでページ開ける コールバックも書ける

page = new WebPage()
page.open 'http://google.com', (status) ->
  console.log '通信しました'
  phantom.exit()

コールバックは指定したURLがロードされたときに実行されるのではなくて,WebPageのロードが完了したら毎回呼ばれる
インスタンスごとに設定するみたいなイメージ
いろいろ並列に取りたいときはWebPageのインスタンスを別にする

page1 = new WebPage()
page1.open 'http://google.com', (status) ->
  href = page1.evaluate ->
    location.href
  console.log "通信しました(1) #{href}"

page2 = new WebPage()
page2.open 'http://bit.ly', (status) ->
  href = page2.evaluate ->
    location.href
  console.log "通信しました(2) #{href}"

page3 = new WebPage()
page3.open 'http://hatenablog.com', (status) ->
  href = page3.evaluate ->
    location.href
  console.log "通信しました(3) #{href}"

昨日見てると,phantom.state++とかして何回通信したかで処理を変えるのを見た
けっこうひどい感じがする,ほかに良い書き方ありそう,location.hrefを正規表現にマッチさせて処理を書くとかのほうがいい気がする

phantom.state = 0
page = new WebPage()
page.open url, (status) ->
  try
    phantom.state++
    if status != 'success'
      phantom.exit(1)

    switch phantom.state
      when 1
        # 1回目

      when 2
        # 2回目
  catch error
    phantom.exit(1)

DOM操作

WebPage#evaluateでページのコンテキストでスクリプトを実行できる

page.evaluate ->
  document.querySelector('textarea').value

documentとか取れるので何でもできる
ただし,functionを渡せるだけで,クロージャとかで外から変数渡したりできない
ということは,起動時にメッセージを書いてその内容を掲示板にポストとかはできない?(誰か知ってたら教えてほしい)
返り値は取れる

evaluateの中でconsole.logしても何もでてこない,ブラウザの中のconsole.logが呼ばれているため?
例外をcatchしないとスタックトレースとか出ずに処理が終了する場合がある

デバッグ

WebPage#render(ファイル名)でスクリーンショット取れる
スクリーンショットを見て,ちゃんとページが取れてるか確認してデバッグすると効率良い.

window.setTimeout ->
  page.render 'a.png'
, 200

終了

phantom.exit()しないと終了しないので終わりたいと思ったところに書いておく

phantom.open

検索するとWebPage#openではなくてphantom.openを使ってるのがあった.
手元のphantomにはphantom.openない.
APIが変わった?

印象

ブラウザと同じように動くのは便利だけど書きにくい.
JSでDOM操作できれば慣れてるから他の慣れてるスクリプト言語で書くより速いかと思ったけど,通信するところが,コールバックが変な感じだったり,デバッグしにくかったりして,なかなか難しかった.
スクレイピングに使うには,ページ側のJSが動かないとどうしても書けないという場合以外には使わなくてよさそう.
昨日作ったのは以下で,診断メーカーをランダムに受診して結果を表示する,というもの.


ページのJSのテストとかで使うには良い気がする.