More Related Content Similar to Wight: Phantom’s Perl friend - YAPC::Asia 2012 (20) Wight: Phantom’s Perl friend - YAPC::Asia 20122. About myself
• 株式会社はてな
• id:motemen
• github:motemen
• cpan:MOTEMEN
- App::htmlcat
- AnyEvent::DAAP::Server
• twitter:美顔器
11. PhantomJS
“PhantomJS is a headless WebKit with
JavaScript API. It has fast and native
support for various web standards:
DOM handling, CSS selector, JSON,
Canvas, and SVG.”
— http://phantomjs.org/
12. PhantomJS
“PhantomJS is a headless WebKit with
JavaScript API. It has fast and native
support for various web standards:
DOM handling, CSS selector, JSON,
Canvas, and SVG.”
— http://phantomjs.org/
15. JavaScript API
var page = require('webpage').create();
var url = 'http://www.phantomjs.org/';
page.open(url, function (status) {
//Page is loaded!
phantom.exit();
});
• PhantomJS の JS API でブラウジング
- new WebPage()
• Web ページとは別のコンテキストで実行
16. インストール
_
( ・ω・)
_(__つ/ ̄ ̄ ̄/
\/ /
 ̄ ̄ ̄\
\┗(^o^ )┛┗(^o^ )┛┗(^o^ )┛ ┗( ^o^)┛
\┏┗ ┏┗ ┏┗ ┛┓
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
• バイナリ
- phantomjs.org/download.html
• brew install phantomjs
22. “Wight”
"Wight is a Middle English word, from
Old English wiht, and used to describe a
creature or living sentient being. It is
akin to Old High German wiht, meaning
a creature or thing."
24. SYNOPSIS
use Wight;
my $w = Wight->new;
$w->visit('https://www.google.com/');
$w->find('//input[@name="q"]')->set('motemen');
$w->find('//input[@type="submit"]')->click();
foreach ($w->find('//h3[@class="r"]/a')) {
say ' * ', $_->text;
}
25. Wight->new
use Wight;
my $w = Wight->new;
$w->visit('https://www.google.com/');
•PhantomJS を起動
$w->find('//input[@name="q"]')->set('motemen');
$w->find('//input[@type="submit"]')->click();
•通信を確立
foreach ($w->find('//h3[@class="r"]/a')) {
say ' * ', $_->text;
}
26. $w->visit($url)
use Wight;
my $w = Wight->new;
$w->visit('https://www.google.com/');
$w->find('//input[@name="q"]')->set('motemen');
$w->find('//input[@type="submit"]')->click();
•URL を開く
foreach ($w->find('//h3[@class="r"]/a')) {
say ' * ', $_->text;
}
27. $node = $w->find($xpath)
@nodes = $w->find($xpath)
use Wight;
•XPathWight->new;
my $w =
でページ内の要素へアクセス
$w->visit('https://www.google.com/');
$w->find('//input[@name="q"]')->set('motemen');
$w->find('//input[@type="submit"]')->click();
foreach ($w->find('//h3[@class="r"]/a')) {
say ' * ', $_->text;
}
29. $node->click()
•要素をクリック
use Wight;
my $w = Wight->new;
•クリックできない場所にあったらエラー
$w->visit('https://www.google.com/');
$w->find('//input[@name="q"]')->set('motemen');
$w->find('//input[@type="submit"]')->click();
foreach ($w->find('//h3[@class="r"]/a')) {
say ' * ', $_->text;
}
33. $w->cookie_jar
• PhantomJS Perl でクッキー受け渡し
• HTTP::Cookies
my $w = Wight->new(cookie => 1);
some_complicated_authentication();
my $cookie_jar = $w->reload_cookie_jar;
my $ua = LWP::UserAgent->new(
cookie_jar => $cookie_jar
);
usual_downloading_routine();
36. Test::Wight
my $w = Test::Wight->new;
my $port = $w->spawn_psgi($app);
$w->visit('/');
is $w->evaluate('document.title'), 'title';
my $link = $wight->find('//p/a')
$link->click;
is $w->current_url->path, '/foo';
46. 出演者
• ( ╹◡╹) Perl
• (´⊙ω⊙) PhantomJS
• ( ˘ω˘) Page Content
47. Perl PhantomJS
• Wight->new
- Twiggy を起動
- PhantomJS を起動
- WebSocket 接続を待つ
• connection.js
this.socket =
new WebSocket("ws://127.0.0.1:" + this.port + "/");
this.socket.onmessage = this.commandReceived;
48. Perl PhantomJS
• $w->call($method, @args)
- WebSocket メッセージを送信
- $cv->recv してじっと待つ
• main.js / browser.js
- 結果 (エラー) が出しだい返答
- リンクのクリックの場合 URL が変わるまで
49. PhantomJS Page Content
• browser.js, web_page.js
- Perl 側から来た要求を実行
• agent.js をページ内に埋め込み
- 要素の発見
- イベントの発生
51. コールバック
• 非同期な通信は使えない
- WebSocket ×
- Ajax ×
- Synchronous XMLHttpRequest ○
• ふつうに HTTP リクエストをさばく
$w->on_confirm(sub {
my ($w, @args) = @_;
return rand() < 0.5;
});
57. SYNOPSIS
jQuery; # => '$'
jQuery('#foo'); # => '$("#foo")'
jQuery('#foo')->val(); # => '$("#foo").val()'
jQuery('#foo')->val(23); # => '$("#foo").val(23)'
jQuery('document'); # => '$(document)'
jQuery->ajax({ method => 'POST' });
# => '$.ajax({"method":"POST"})'
• 文字列化すると jQuery の式に
• それっぽいメソッドチェーン
Editor's Notes &#x307D;&#x3048;\n \n \n \n \n \n \n \n \n \n \n \n \n HTML&#x306E;&#x30EC;&#x30F3;&#x30C0;&#x30EA;&#x30F3;&#x30B0;&#x3084;JavaScript&#x306E;&#x89E3;&#x91C8;&#x30FB;&#x5B9F;&#x884C;&#x306A;&#x3069;&#x3092;&#x304A;&#x3053;&#x306A;&#x3063;&#x3066;&#x304F;&#x308C;&#x308B;&#x30AA;&#x30FC;&#x30D7;&#x30F3;&#x30BD;&#x30FC;&#x30B9;&#x306E;&#x30A8;&#x30F3;&#x30B8;&#x30F3;&#x3067;&#x3059;\n \n \n &#x7279;&#x5FB4;&#x7684;&#x306A;&#x70B9;&#x306F;&#x30D0;&#x30A4;&#x30CA;&#x30EA;&#x3072;&#x3068;&#x3064;&#x304C;&#x914D;&#x3089;&#x308C;&#x3066;&#x3044;&#x308B;&#x3053;&#x3068;\n &#x3082;&#x3061;&#x308D;&#x3093; GUI &#x306A;&#x3057;\n &#x3053;&#x308C;&#x3092; Perl &#x304B;&#x3089;&#x4F7F;&#x308F;&#x306A;&#x3044;&#x624B;&#x306F;&#x306A;&#x3044;&#x3001;&#x3068;\n \n \n \n \n &#x3053;&#x308C;&#x306F;Google&#x3092;&#x691C;&#x7D22;&#x3059;&#x308B;&#x4F8B;&#x3067;&#x3059;\n \n \n \n \n \n &#x305D;&#x306E;&#x4ED6;&#x306E;&#x3088;&#x304F;&#x4F7F;&#x3046;&#x30E1;&#x30BD;&#x30C3;&#x30C9;&#x3068;&#x3057;&#x3066;&#x306F;&#x3001;&#x30B9;&#x30AF;&#x30EA;&#x30FC;&#x30F3;&#x30B7;&#x30E7;&#x30C3;&#x30C8;&#x3092;&#x753B;&#x50CF;&#x30D5;&#x30A1;&#x30A4;&#x30EB;&#x306B;&#x66F8;&#x304D;&#x51FA;&#x3059;render\n&#x3053;&#x3046;&#x3057;&#x3066;&#x898B;&#x308B;&#x3068;&#x3001;&#x3061;&#x3083;&#x3093;&#x3068;&#x5185;&#x90E8;&#x3067;&#x306F;&#x8981;&#x7D20;&#x306E;&#x914D;&#x7F6E;&#x306A;&#x3069;&#x304C;&#x884C;&#x308F;&#x308C;&#x3066;&#x3044;&#x308B;&#x306E;&#x304C;&#x308F;&#x304B;&#x308B;\n \n \n JS &#x306E;&#x8981;&#x308B;&#x9762;&#x5012;&#x306A;&#x3068;&#x3053;&#x308D;&#x3060;&#x3051; PhantomJS &#x3092;&#x4F7F;&#x3063;&#x3066;&#x3001;Mechanize &#x3042;&#x3068;&#x306F;&#x983C;&#x3093;&#x3060;&#x3068;&#x3044;&#x3046;&#x3088;&#x3046;&#x306A;&#x3053;&#x3068;&#x304C;&#x3067;&#x304D;&#x307E;&#x3059;\n \n \n \n &#x30A4;&#x30F3;&#x30BF;&#x30FC;&#x30CD;&#x30C3;&#x30C8;&#x4E0A;&#x306E;&#x30B5;&#x30FC;&#x30D0;&#x306B;&#x30A2;&#x30AF;&#x30BB;&#x30B9;&#x305B;&#x305A;&#x3001;&#x5185;&#x90E8;&#x3067;&#x30A2;&#x30AF;&#x30BB;&#x30B9;&#x3092;&#x9589;&#x3058;&#x305F;&#x3044;&#x5834;&#x5408;&#x306B;\nfork &#x306F; Twiggy &#x4EE5;&#x5916;&#x306E;&#x30B5;&#x30FC;&#x30D0;&#x3092;&#x4F7F;&#x3044;&#x305F;&#x3044;&#x3068;&#x304D;&#x306A;&#x3069;\ntwiggy &#x3092;&#x4F7F;&#x3046;&#x3068;&#x30EA;&#x30AF;&#x30A8;&#x30B9;&#x30C8;&#x3055;&#x308C;&#x305F; $env &#x3092;&#x30C6;&#x30B9;&#x30C8;&#x5185;&#x304B;&#x3089;&#x305D;&#x306E;&#x307E;&#x307E;&#x53C2;&#x7167;&#x3067;&#x304D;&#x307E;&#x3059;\n \n \n \n \n \n \n \n \n \n \n phantomjs &#x3092;&#x8D77;&#x52D5;&#x3057;&#x3066; WebSocket &#x63A5;&#x7D9A;&#x304C;&#x78BA;&#x7ACB;&#x3059;&#x308B;&#x307E;&#x3067; sleep &#x3057;&#x307E;&#x3059;\n Wight &#x306E;&#x307B;&#x3068;&#x3093;&#x3069;&#x306E; API &#x306F; &#x3053;&#x306E; call &#x3068;&#x3044;&#x3046;&#x306E;&#x3092;&#x7D4C;&#x7531;&#x3057;&#x307E;&#x3059;\n &#x5F85;&#x3061;&#x53D7;&#x3051;&#x305F; poltergeist &#x3067;&#x306F;&#x3001;phantomjs &#x306E; API &#x3092;&#x53E9;&#x3044;&#x3066;&#x30A6;&#x30A7;&#x30D6;&#x30DA;&#x30FC;&#x30B8;&#x306E;&#x64CD;&#x4F5C;&#x3084;&#x60C5;&#x5831;&#x53D6;&#x5F97;&#x3092;&#x304A;&#x3053;&#x306A;&#x3044;&#x307E;&#x3059;\n Perl &#x5074;&#x304B;&#x3089;&#x30A2;&#x30AF;&#x30B7;&#x30E7;&#x30F3;&#x3059;&#x308B;&#x306E;&#x3067;&#x306F;&#x306A;&#x304F;&#x30DA;&#x30FC;&#x30B8;&#x5074;&#x304B;&#x3089;&#x30A4;&#x30D9;&#x30F3;&#x30C8;&#x304C;&#x98DB;&#x3093;&#x3067;&#x304F;&#x308B;&#x3088;&#x3046;&#x306A;&#x5834;&#x5408;\n \n \n \n \n \n \n \n \n \n \n