Perl でファントムする! 改めWight - Phantoms   new friend   YAPC::Asia 2012      motemen
About myself• 株式会社はてな• id:motemen • github:motemen • cpan:MOTEMEN  - App::htmlcat - AnyEvent::DAAP::Server • twitter:美顔器
Perl で楽しいこと1.スクレイピングする2.ウェブサービスを作る3.その他
スクレイピングはみんな好き• WWW::Mechanize• Web::Scraper• Web::Query• Plagger
近年の JavaScript の隆盛
PhantomJS    テキスト
PhantomJS• Ariya Hidayat 氏• できること- インターネット       テキスト- ただし見えない
PhantomJS“PhantomJS is a headless WebKit withJavaScript API. It has fast and nativesupport for various web standards:DOM h...
PhantomJS“PhantomJS is a headless WebKit withJavaScript API. It has fast and nativesupport for various web standards:DOM h...
WebKit• Web レンダリングエンジン - HTML, JavaScript, … • Safari / Chrome
Headless• ユーザ向けの(目に見える)インター フェースなし
JavaScript API    var page = require(webpage).create();    var url = http://www.phantomjs.org/;    page.open(url, function...
インストール       _      (  ・ω・)    _(__つ/ ̄ ̄ ̄/      \/   /         ̄ ̄ ̄\             \┗(^o^ )┛┗(^o^ )┛┗(^o^ )┛  ┗( ^o^)┛         ...
使う
PhantomJS is for…• Scraping• JavaScript testing• Network monitorning
“Wight”
“Wight”"Wight is a Middle English word, fromOld English wiht, and used to describe acreature or living sentient being. It ...
キラキラネームの理由(わけ)• CasperJS (JavaScript)• Poltergeist (Ruby)• GhostDriver (JavaScript)• …etc
SYNOPSIS use Wight; my $w = Wight->new; $w->visit(https://www.google.com/); $w->find(//input[@name="q"])->set(motemen); $w...
Wight->new  use Wight;  my $w = Wight->new;  $w->visit(https://www.google.com/);•PhantomJS を起動 $w->find(//input[@name="q"]...
$w->visit($url)  use Wight;  my $w = Wight->new;  $w->visit(https://www.google.com/);  $w->find(//input[@name="q"])->set(m...
$node = $w->find($xpath)@nodes = $w->find($xpath) use Wight;•XPathWight->new; my $w =         でページ内の要素へアクセス $w->visit(http...
$node->set($value)•要素の値を設定 use Wight;•あわせてキーイベントも発生(!) my $w = Wight->new; $w->visit(https://www.google.com/); $w->find(//...
$node->click()•要素をクリック use Wight; my $w = Wight->new;•クリックできない場所にあったらエラー $w->visit(https://www.google.com/); $w->find(//in...
$w->render($filename)
$w->evaluate($JavaScript) $w->evaluate(document.title); # => "はてな" $w->evaluate(document.body.getBoundingClientRect()) # {...
$w->execute($JavaScript) $w->execute(<<JAVASCRIPT);   var nodes = document.querySelectorAll(img);   [].slice.call(nodes).f...
$w->cookie_jar• PhantomJS Perl でクッキー受け渡し• HTTP::Cookies my $w = Wight->new(cookie => 1); some_complicated_authentication()...
•$w->body•$w->source•$w->current_url•$node->visible•$node->attribute($name)•$node->value•etc…
Testing
Test::Wight my $w = Test::Wight->new; my $port = $w->spawn_psgi($app); $w->visit(/); is $w->evaluate(document.title), titl...
Test::Wight• 内部でアクセスを閉じたい場合に• $port = $w->spawn_psgi($app)  - ‘fork’ or ‘twiggy’
Why Perl?• コールバックのない平坦なコードに• CPAN モジュールの再利用 - LWP family  - Coro による並列化• Perl アプリケーションからの利用• prove したい
Example
Tumblr dashboard• “J” キーの押下をエミュレート• img 要素の href を取得• (ダウンロード)は Perl に任せる
IMPLEMENTATION
Uses Poltergeistgithub.com/jonleighton/poltergeist
Poltergeist• “A PhantomJS driver for Capybara” • Jon Leighton 氏• これの JavaScript を流用• ルビースト最高!
出演者• ( ╹◡╹) Perl• (´⊙ω⊙) PhantomJS• ( ˘ω˘) Page Content
Perl      PhantomJS• Wight->new  - Twiggy を起動 - PhantomJS を起動 - WebSocket 接続を待つ• connection.js this.socket =   new WebSock...
Perl   PhantomJS• $w->call($method, @args)  - WebSocket メッセージを送信 - $cv->recv してじっと待つ• main.js / browser.js  - 結果 (エラー) が出し...
PhantomJS    Page Content• browser.js, web_page.js  - Perl 側から来た要求を実行• agent.js をページ内に埋め込み- 要素の発見- イベントの発生
コールバック// in PhantomJSpage.onPrompt = function () {   return answer;};• 関数の返り値がユーザの返答代わり
コールバック• 非同期な通信は使えない - WebSocket × - Ajax × - Synchronous XMLHttpRequest ○ • ふつうに HTTP リクエストをさばく$w->on_confirm(sub {    my ...
TODO• Mechanize 等との連携• フレーム対応 - PhantomJS 1.7 ∼• poltergeist に pull-req- (ルビーストになりたい)
おまけ
jQuery (☝◞‸◟)☝…$w->evaluate($("img").attr("src"));
jQuery └( ^ω^ )」♪$w->evaluate(jQuery(img)->attr(src));
Wight::jQuery
SYNOPSISjQuery; # => $jQuery(#foo); # => $("#foo")jQuery(#foo)->val(); # => $("#foo").val()jQuery(#foo)->val(23); # => $("...
プロパティ/コールバックjQuery(body)->position().left;# => $("body").position().leftjQuery(body)->click(sub {  e => console.log(e); re...
まとめ• PhantomJS • Wight - スクレイピングやテストに使えます- API と実装の紹介
github.com/motemen/Wight
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Upcoming SlideShare
Loading in...5
×

Wight: Phantom’s Perl friend - YAPC::Asia 2012

11,739

Published on

A Perl implementation which manipulates phantomjs from Perl's side.

Published in: Technology
0 Comments
10 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
11,739
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
14
Comments
0
Likes
10
Embeds 0
No embeds

No notes for slide
  • &amp;#x307D;&amp;#x3048;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • HTML&amp;#x306E;&amp;#x30EC;&amp;#x30F3;&amp;#x30C0;&amp;#x30EA;&amp;#x30F3;&amp;#x30B0;&amp;#x3084;JavaScript&amp;#x306E;&amp;#x89E3;&amp;#x91C8;&amp;#x30FB;&amp;#x5B9F;&amp;#x884C;&amp;#x306A;&amp;#x3069;&amp;#x3092;&amp;#x304A;&amp;#x3053;&amp;#x306A;&amp;#x3063;&amp;#x3066;&amp;#x304F;&amp;#x308C;&amp;#x308B;&amp;#x30AA;&amp;#x30FC;&amp;#x30D7;&amp;#x30F3;&amp;#x30BD;&amp;#x30FC;&amp;#x30B9;&amp;#x306E;&amp;#x30A8;&amp;#x30F3;&amp;#x30B8;&amp;#x30F3;&amp;#x3067;&amp;#x3059;\n
  • \n
  • \n
  • &amp;#x7279;&amp;#x5FB4;&amp;#x7684;&amp;#x306A;&amp;#x70B9;&amp;#x306F;&amp;#x30D0;&amp;#x30A4;&amp;#x30CA;&amp;#x30EA;&amp;#x3072;&amp;#x3068;&amp;#x3064;&amp;#x304C;&amp;#x914D;&amp;#x3089;&amp;#x308C;&amp;#x3066;&amp;#x3044;&amp;#x308B;&amp;#x3053;&amp;#x3068;\n
  • &amp;#x3082;&amp;#x3061;&amp;#x308D;&amp;#x3093; GUI &amp;#x306A;&amp;#x3057;\n
  • &amp;#x3053;&amp;#x308C;&amp;#x3092; Perl &amp;#x304B;&amp;#x3089;&amp;#x4F7F;&amp;#x308F;&amp;#x306A;&amp;#x3044;&amp;#x624B;&amp;#x306F;&amp;#x306A;&amp;#x3044;&amp;#x3001;&amp;#x3068;\n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x3053;&amp;#x308C;&amp;#x306F;Google&amp;#x3092;&amp;#x691C;&amp;#x7D22;&amp;#x3059;&amp;#x308B;&amp;#x4F8B;&amp;#x3067;&amp;#x3059;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • &amp;#x305D;&amp;#x306E;&amp;#x4ED6;&amp;#x306E;&amp;#x3088;&amp;#x304F;&amp;#x4F7F;&amp;#x3046;&amp;#x30E1;&amp;#x30BD;&amp;#x30C3;&amp;#x30C9;&amp;#x3068;&amp;#x3057;&amp;#x3066;&amp;#x306F;&amp;#x3001;&amp;#x30B9;&amp;#x30AF;&amp;#x30EA;&amp;#x30FC;&amp;#x30F3;&amp;#x30B7;&amp;#x30E7;&amp;#x30C3;&amp;#x30C8;&amp;#x3092;&amp;#x753B;&amp;#x50CF;&amp;#x30D5;&amp;#x30A1;&amp;#x30A4;&amp;#x30EB;&amp;#x306B;&amp;#x66F8;&amp;#x304D;&amp;#x51FA;&amp;#x3059;render\n&amp;#x3053;&amp;#x3046;&amp;#x3057;&amp;#x3066;&amp;#x898B;&amp;#x308B;&amp;#x3068;&amp;#x3001;&amp;#x3061;&amp;#x3083;&amp;#x3093;&amp;#x3068;&amp;#x5185;&amp;#x90E8;&amp;#x3067;&amp;#x306F;&amp;#x8981;&amp;#x7D20;&amp;#x306E;&amp;#x914D;&amp;#x7F6E;&amp;#x306A;&amp;#x3069;&amp;#x304C;&amp;#x884C;&amp;#x308F;&amp;#x308C;&amp;#x3066;&amp;#x3044;&amp;#x308B;&amp;#x306E;&amp;#x304C;&amp;#x308F;&amp;#x304B;&amp;#x308B;\n
  • \n
  • \n
  • JS &amp;#x306E;&amp;#x8981;&amp;#x308B;&amp;#x9762;&amp;#x5012;&amp;#x306A;&amp;#x3068;&amp;#x3053;&amp;#x308D;&amp;#x3060;&amp;#x3051; PhantomJS &amp;#x3092;&amp;#x4F7F;&amp;#x3063;&amp;#x3066;&amp;#x3001;Mechanize &amp;#x3042;&amp;#x3068;&amp;#x306F;&amp;#x983C;&amp;#x3093;&amp;#x3060;&amp;#x3068;&amp;#x3044;&amp;#x3046;&amp;#x3088;&amp;#x3046;&amp;#x306A;&amp;#x3053;&amp;#x3068;&amp;#x304C;&amp;#x3067;&amp;#x304D;&amp;#x307E;&amp;#x3059;\n
  • \n
  • \n
  • \n
  • &amp;#x30A4;&amp;#x30F3;&amp;#x30BF;&amp;#x30FC;&amp;#x30CD;&amp;#x30C3;&amp;#x30C8;&amp;#x4E0A;&amp;#x306E;&amp;#x30B5;&amp;#x30FC;&amp;#x30D0;&amp;#x306B;&amp;#x30A2;&amp;#x30AF;&amp;#x30BB;&amp;#x30B9;&amp;#x305B;&amp;#x305A;&amp;#x3001;&amp;#x5185;&amp;#x90E8;&amp;#x3067;&amp;#x30A2;&amp;#x30AF;&amp;#x30BB;&amp;#x30B9;&amp;#x3092;&amp;#x9589;&amp;#x3058;&amp;#x305F;&amp;#x3044;&amp;#x5834;&amp;#x5408;&amp;#x306B;\nfork &amp;#x306F; Twiggy &amp;#x4EE5;&amp;#x5916;&amp;#x306E;&amp;#x30B5;&amp;#x30FC;&amp;#x30D0;&amp;#x3092;&amp;#x4F7F;&amp;#x3044;&amp;#x305F;&amp;#x3044;&amp;#x3068;&amp;#x304D;&amp;#x306A;&amp;#x3069;\ntwiggy &amp;#x3092;&amp;#x4F7F;&amp;#x3046;&amp;#x3068;&amp;#x30EA;&amp;#x30AF;&amp;#x30A8;&amp;#x30B9;&amp;#x30C8;&amp;#x3055;&amp;#x308C;&amp;#x305F; $env &amp;#x3092;&amp;#x30C6;&amp;#x30B9;&amp;#x30C8;&amp;#x5185;&amp;#x304B;&amp;#x3089;&amp;#x305D;&amp;#x306E;&amp;#x307E;&amp;#x307E;&amp;#x53C2;&amp;#x7167;&amp;#x3067;&amp;#x304D;&amp;#x307E;&amp;#x3059;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • phantomjs &amp;#x3092;&amp;#x8D77;&amp;#x52D5;&amp;#x3057;&amp;#x3066; WebSocket &amp;#x63A5;&amp;#x7D9A;&amp;#x304C;&amp;#x78BA;&amp;#x7ACB;&amp;#x3059;&amp;#x308B;&amp;#x307E;&amp;#x3067; sleep &amp;#x3057;&amp;#x307E;&amp;#x3059;\n
  • Wight &amp;#x306E;&amp;#x307B;&amp;#x3068;&amp;#x3093;&amp;#x3069;&amp;#x306E; API &amp;#x306F; &amp;#x3053;&amp;#x306E; call &amp;#x3068;&amp;#x3044;&amp;#x3046;&amp;#x306E;&amp;#x3092;&amp;#x7D4C;&amp;#x7531;&amp;#x3057;&amp;#x307E;&amp;#x3059;\n
  • &amp;#x5F85;&amp;#x3061;&amp;#x53D7;&amp;#x3051;&amp;#x305F; poltergeist &amp;#x3067;&amp;#x306F;&amp;#x3001;phantomjs &amp;#x306E; API &amp;#x3092;&amp;#x53E9;&amp;#x3044;&amp;#x3066;&amp;#x30A6;&amp;#x30A7;&amp;#x30D6;&amp;#x30DA;&amp;#x30FC;&amp;#x30B8;&amp;#x306E;&amp;#x64CD;&amp;#x4F5C;&amp;#x3084;&amp;#x60C5;&amp;#x5831;&amp;#x53D6;&amp;#x5F97;&amp;#x3092;&amp;#x304A;&amp;#x3053;&amp;#x306A;&amp;#x3044;&amp;#x307E;&amp;#x3059;\n
  • Perl &amp;#x5074;&amp;#x304B;&amp;#x3089;&amp;#x30A2;&amp;#x30AF;&amp;#x30B7;&amp;#x30E7;&amp;#x30F3;&amp;#x3059;&amp;#x308B;&amp;#x306E;&amp;#x3067;&amp;#x306F;&amp;#x306A;&amp;#x304F;&amp;#x30DA;&amp;#x30FC;&amp;#x30B8;&amp;#x5074;&amp;#x304B;&amp;#x3089;&amp;#x30A4;&amp;#x30D9;&amp;#x30F3;&amp;#x30C8;&amp;#x304C;&amp;#x98DB;&amp;#x3093;&amp;#x3067;&amp;#x304F;&amp;#x308B;&amp;#x3088;&amp;#x3046;&amp;#x306A;&amp;#x5834;&amp;#x5408;\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Wight: Phantom’s Perl friend - YAPC::Asia 2012

    1. 1. Perl でファントムする! 改めWight - Phantoms new friend YAPC::Asia 2012 motemen
    2. 2. About myself• 株式会社はてな• id:motemen • github:motemen • cpan:MOTEMEN  - App::htmlcat - AnyEvent::DAAP::Server • twitter:美顔器
    3. 3. Perl で楽しいこと1.スクレイピングする2.ウェブサービスを作る3.その他
    4. 4. スクレイピングはみんな好き• WWW::Mechanize• Web::Scraper• Web::Query• Plagger
    5. 5. 近年の JavaScript の隆盛
    6. 6. PhantomJS テキスト
    7. 7. PhantomJS• Ariya Hidayat 氏• できること- インターネット テキスト- ただし見えない
    8. 8. PhantomJS“PhantomJS is a headless WebKit withJavaScript API. It has fast and nativesupport for various web standards:DOM handling, CSS selector, JSON,Canvas, and SVG.” — http://phantomjs.org/
    9. 9. PhantomJS“PhantomJS is a headless WebKit withJavaScript API. It has fast and nativesupport for various web standards:DOM handling, CSS selector, JSON,Canvas, and SVG.” — http://phantomjs.org/
    10. 10. WebKit• Web レンダリングエンジン - HTML, JavaScript, … • Safari / Chrome
    11. 11. Headless• ユーザ向けの(目に見える)インター フェースなし
    12. 12. 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 ページとは別のコンテキストで実行
    13. 13. インストール    _   (  ・ω・) _(__つ/ ̄ ̄ ̄/   \/   /      ̄ ̄ ̄\          \┗(^o^ )┛┗(^o^ )┛┗(^o^ )┛  ┗( ^o^)┛           \┏┗   ┏┗   ┏┗      ┛┓             ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄• バイナリ- phantomjs.org/download.html • brew install phantomjs
    14. 14. 使う
    15. 15. PhantomJS is for…• Scraping• JavaScript testing• Network monitorning
    16. 16. “Wight”
    17. 17. “Wight”"Wight is a Middle English word, fromOld English wiht, and used to describe acreature or living sentient being. It isakin to Old High German wiht, meaninga creature or thing."
    18. 18. キラキラネームの理由(わけ)• CasperJS (JavaScript)• Poltergeist (Ruby)• GhostDriver (JavaScript)• …etc
    19. 19. 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; }
    20. 20. 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; }
    21. 21. $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; }
    22. 22. $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; }
    23. 23. $node->set($value)•要素の値を設定 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; }
    24. 24. $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; }
    25. 25. $w->render($filename)
    26. 26. $w->evaluate($JavaScript) $w->evaluate(document.title); # => "はてな" $w->evaluate(document.body.getBoundingClientRect()) # { # bottom => 1363, # height => 1363, # left => 0, # right => 1024, # top => 0, # width => 1024 # }
    27. 27. $w->execute($JavaScript) $w->execute(<<JAVASCRIPT); var nodes = document.querySelectorAll(img); [].slice.call(nodes).forEach(function () { … }); JAVASCRIPT # => JSON::XS::true
    28. 28. $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();
    29. 29. •$w->body•$w->source•$w->current_url•$node->visible•$node->attribute($name)•$node->value•etc…
    30. 30. Testing
    31. 31. 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;
    32. 32. Test::Wight• 内部でアクセスを閉じたい場合に• $port = $w->spawn_psgi($app)  - ‘fork’ or ‘twiggy’
    33. 33. Why Perl?• コールバックのない平坦なコードに• CPAN モジュールの再利用 - LWP family  - Coro による並列化• Perl アプリケーションからの利用• prove したい
    34. 34. Example
    35. 35. Tumblr dashboard• “J” キーの押下をエミュレート• img 要素の href を取得• (ダウンロード)は Perl に任せる
    36. 36. IMPLEMENTATION
    37. 37. Uses Poltergeistgithub.com/jonleighton/poltergeist
    38. 38. Poltergeist• “A PhantomJS driver for Capybara” • Jon Leighton 氏• これの JavaScript を流用• ルビースト最高!
    39. 39. 出演者• ( ╹◡╹) Perl• (´⊙ω⊙) PhantomJS• ( ˘ω˘) Page Content
    40. 40. 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;
    41. 41. Perl PhantomJS• $w->call($method, @args)  - WebSocket メッセージを送信 - $cv->recv してじっと待つ• main.js / browser.js  - 結果 (エラー) が出しだい返答 - リンクのクリックの場合 URL が変わるまで
    42. 42. PhantomJS Page Content• browser.js, web_page.js  - Perl 側から来た要求を実行• agent.js をページ内に埋め込み- 要素の発見- イベントの発生
    43. 43. コールバック// in PhantomJSpage.onPrompt = function () { return answer;};• 関数の返り値がユーザの返答代わり
    44. 44. コールバック• 非同期な通信は使えない - WebSocket × - Ajax × - Synchronous XMLHttpRequest ○ • ふつうに HTTP リクエストをさばく$w->on_confirm(sub { my ($w, @args) = @_; return rand() < 0.5;});
    45. 45. TODO• Mechanize 等との連携• フレーム対応 - PhantomJS 1.7 ∼• poltergeist に pull-req- (ルビーストになりたい)
    46. 46. おまけ
    47. 47. jQuery (☝◞‸◟)☝…$w->evaluate($("img").attr("src"));
    48. 48. jQuery └( ^ω^ )」♪$w->evaluate(jQuery(img)->attr(src));
    49. 49. Wight::jQuery
    50. 50. SYNOPSISjQuery; # => $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 の式に• それっぽいメソッドチェーン
    51. 51. プロパティ/コールバックjQuery(body)->position().left;# => $("body").position().leftjQuery(body)->click(sub { e => console.log(e); return false});# => $("body").click(function (e){ console.log(e); return false })
    52. 52. まとめ• PhantomJS • Wight - スクレイピングやテストに使えます- API と実装の紹介
    53. 53. github.com/motemen/Wight
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×