0

HerokuでSinatra+PhantomJS

ためしに、URLを入れるとaタグのhref属性とxy座標と幅と高さが取れる簡単なアプリを作ってみた。herokuでwebkitが動いててサーバー側でいったんページをレンダリングしてるから、座標とかがわかる。

http://phantom-getlinks.herokuapp.com/


ソースコード https://github.com/shokai/sinatra-heroku-phantomjs

readmeに書いてある通りやればローカルでもHerokuでもすぐ動かせるのでcloneしてみるとよい。


PhantomJSでページをレンダリングしてからaタグの座標とか読む


PhantomJSはプロセス内にwebブラウザ(webkit)を起動して、しかもその中のJavaScriptにアクセスできる
橋本商会 » PhantomJSでwebページ内のJavaScriptを読む


PhantomJSでページに注釈を付けてスクリーンショット撮るやつ – hitode909の日記
を見ていたら、injectJSという関数でPhantomJS内のwebkitにjQueryを読み込ませて好き勝手やってた。

hitodeさんのを参考にして、aタグの位置とかをJSONで吐き出すスクリプトを用意した。


HerokuでPhantomJSとRubyを同時に使えるようにする


まずローカルでSinatraアプリを普通に作る。phantomjsコマンドを呼び出して結果のJSONをブラウザに返すアプリを作る。

それをHerokuで動かすにはbuildpack機能を使う。1つのアプリでRubyとPhantomJSが同時に使えるようになる。

参考:herokuでRubyとphantomjsを使う #Ruby #heroku #PhantomJS – Qiita


create –stack cederの代わりにbuildpackを指定してアプリを作る
% heroku create --buildpack git://github.com/ddollar/heroku-buildpack-multi.git

.buildpacksファイルを作る
https://github.com/stomita/heroku-buildpack-phantomjs.git
https://github.com/heroku/heroku-buildpack-ruby.git
この2行を書く。

あとは普段どおりGemfile, Gemfile.lock, Procfileと.buildpacksをgit addしてcommitして、herokuにgit pushする。

最後に環境変数を設定して、phantomjsコマンドにパスが通って完了
% heroku config:add LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:/lib:/app/vendor/phantomjs/lib
% heroku config:add PATH=bin:vendor/bundle/ruby/1.9.1/bin:/usr/local/bin:/usr/bin:/bin:/app/vendor/phantomjs/bin

ローカルでもHerokuでも問題なく動く。

0

PhantomJSでwebページ内のJavaScriptを読む

Webページをスクレイピングしてる時、HTMLじゃなくてJavaScriptの変数をのぞきたい事が稀によくある。

インストール

brew install phantomjs


document.titleを取得


page_title.js
var url = phantom.args[0] || 'http://shokai.org';

page = new WebPage();
page.open(url, function(stat){
if(!stat){
phantom.exit();
}
else{
var title = page.evaluate(function(){
return document.title;
});
console.log(title);
phantom.exit();
}
});
実行
phantomjs page_title.js http://google.com


titleのような1つの文字列だけでなく、オブジェクトもそのまま取り出せる。


ちょっと待ってから取得

onLoad後にajaxで何かデータ取得してる系のサイトで使う。
setTimeoutでちょっと待てばいい。
var url = phantom.args[0] || 'http://shokai.org';

page = new WebPage();
page.open(url, function(stat){
if(!stat){
phantom.exit();
}
else{
setTimeout(function(){
var title = page.evaluate(function(){
return document.title;
});
console.log(title);
phantom.exit();
}, 3000); // ちょっと待ってから取得
}
});


Basic認証


openする前にsettingsに書いておけばok
page = new WebPage();
page.settings.userName = "shokai";
page.settings.password = "zanmai";