Your SlideShare is downloading. ×
Wight: Phantom’s Perl friend - YAPC::Asia 2012
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

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

11,411
views

Published on

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

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,411
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
14
Comments
0
Likes
10
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • ぽえ\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • HTMLのレンダリングやJavaScriptの解釈・実行などをおこなってくれるオープンソースのエンジンです\n
  • \n
  • \n
  • 特徴的な点はバイナリひとつが配られていること\n
  • もちろん GUI なし\n
  • これを Perl から使わない手はない、と\n
  • \n
  • \n
  • \n
  • \n
  • これはGoogleを検索する例です\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • その他のよく使うメソッドとしては、スクリーンショットを画像ファイルに書き出すrender\nこうして見ると、ちゃんと内部では要素の配置などが行われているのがわかる\n
  • \n
  • \n
  • JS の要る面倒なところだけ PhantomJS を使って、Mechanize あとは頼んだというようなことができます\n
  • \n
  • \n
  • \n
  • インターネット上のサーバにアクセスせず、内部でアクセスを閉じたい場合に\nfork は Twiggy 以外のサーバを使いたいときなど\ntwiggy を使うとリクエストされた $env をテスト内からそのまま参照できます\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • phantomjs を起動して WebSocket 接続が確立するまで sleep します\n
  • Wight のほとんどの API は この call というのを経由します\n
  • 待ち受けた poltergeist では、phantomjs の API を叩いてウェブページの操作や情報取得をおこないます\n
  • Perl 側からアクションするのではなくページ側からイベントが飛んでくるような場合\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • Transcript

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