Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Perl でファントムする! 改め

Wight - Phantom's
   new friend
   YAPC::Asia 2012
      motemen
About myself
• 株式会社はてな
• id:motemen 
• github:motemen 
• cpan:MOTEMEN 
 - App::htmlcat
 - AnyEvent::DAAP::Server 
• twitte...
Perl で楽しいこと
1.スクレイピングする
2.ウェブサービスを作る
3.その他
スクレイピングはみんな好き
• WWW::Mechanize
• Web::Scraper
• Web::Query
• Plagger
近年の JavaScript の隆盛
PhantomJS
    テキスト
PhantomJS
• Ariya Hidayat 氏
• できること
- インターネット       テキスト



- ただし見えない
PhantomJS
“PhantomJS is a headless WebKit with
JavaScript API. It has fast and native
support for various web standards:
D...
PhantomJS
“PhantomJS is a headless WebKit with
JavaScript API. It has fast and native
support for various web standards:
D...
WebKit




• Web レンダリングエンジン
 - HTML, JavaScript, … 
• Safari / Chrome
Headless
• ユーザ向けの(目に見える)インター
 フェースなし
JavaScript API
    var page = require('webpage').create();
    var url = 'http://www.phantomjs.org/';
    page.open(url, f...
インストール
       _
      (  ・ω・)
    _(__つ/ ̄ ̄ ̄/
      \/   /
         ̄ ̄ ̄\ 
            \┗(^o^ )┛┗(^o^ )┛┗(^o^ )┛  ┗( ^o^)┛
  ...
使う
PhantomJS is for…
• Scraping
• JavaScript testing
• Network monitorning
“Wight”
“Wight”
"Wight is a Middle English word, from
Old English wiht, and used to describe a
creature or living sentient being. ...
キラキラネームの理由(わけ)
• 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(...
Wight->new

  use Wight;

  my $w = Wight->new;

  $w->visit('https://www.google.com/');

•PhantomJS を起動
 $w->find('//inpu...
$w->visit($url)

  use Wight;

  my $w = Wight->new;

  $w->visit('https://www.google.com/');

  $w->find('//input[@name="...
$node = $w->find($xpath)
@nodes = $w->find($xpath)
 use Wight;

•XPathWight->new;
 my $w =
         でページ内の要素へアクセス
 $w->vis...
$node->set($value)

•要素の値を設定
 use Wight;


•あわせてキーイベントも発生(!)
 my $w = Wight->new;

 $w->visit('https://www.google.com/');
...
$node->click()

•要素をクリック
 use Wight;

 my $w = Wight->new;
•クリックできない場所にあったらエラー
 $w->visit('https://www.google.com/');

 $w...
$w->render($filename)
$w->evaluate($JavaScript)

 $w->evaluate('document.title'); # => "はてな"


 $w->evaluate('document.body.getBoundingClientRec...
$w->execute($JavaScript)


 $w->execute(<<'JAVASCRIPT');
   var nodes = document.querySelectorAll('img');
   [].slice.call...
$w->cookie_jar
• PhantomJS Perl でクッキー受け渡し
• HTTP::Cookies
 my $w = Wight->new(cookie => 1);
 some_complicated_authenticati...
•$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.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 Poltergeist
github.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 ...
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 PhantomJS
page.onPrompt = function () {
   return answer;
};


• 関数の返り値がユーザの返答代わり
コールバック
• 非同期な通信は使えない
 - WebSocket ×
 - Ajax ×
 - Synchronous XMLHttpRequest ○ 
• ふつうに HTTP リクエストをさばく
$w->on_confirm(sub {
...
TODO
• Mechanize 等との連携
• フレーム対応
 - PhantomJS 1.7 ∼
• poltergeist に pull-req
- (ルビーストになりたい)
おまけ
jQuery
 (☝◞‸◟)☝…
$w->evaluate('$("img").attr("src")');
jQuery
 └( ^ω^ )」♪
$w->evaluate(jQuery('img')->attr('src'));
Wight::jQuery
SYNOPSIS
jQuery; # => '$'

jQuery('#foo'); # => '$("#foo")'
jQuery('#foo')->val(); # => '$("#foo").val()'
jQuery('#foo')->...
プロパティ/コールバック


jQuery('body')->position().'left';
# => '$("body").position().left'

jQuery('body')->click(sub {
  e => 'co...
まとめ
• 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
You’ve finished this document.
Download and read it offline.
Upcoming SlideShare
Network Programming With Anyevent
Next
Upcoming SlideShare
Network Programming With Anyevent
Next
Download to read offline and view in fullscreen.

11

Share

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

Download to read offline

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

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

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

  1. 1. Perl でファントムする! 改め Wight - Phantom's 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 with JavaScript API. It has fast and native support for various web standards: DOM handling, CSS selector, JSON, Canvas, and SVG.” — http://phantomjs.org/
  9. 9. 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/
  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, 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."
  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 Poltergeist github.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 PhantomJS page.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. 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 の式に • それっぽいメソッドチェーン
  51. 51. プロパティ/コールバック jQuery('body')->position().'left'; # => '$("body").position().left' jQuery('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
  • jjmerelo

    May. 7, 2017
  • studioego

    Jun. 1, 2014
  • sak0620

    Jun. 12, 2013
  • ssuser82d97a

    Mar. 5, 2013
  • k0ta0uchi

    Dec. 20, 2012
  • dpavlin

    Oct. 15, 2012
  • sasezaki

    Oct. 5, 2012
  • ywatase

    Oct. 1, 2012
  • KaoruMaeda

    Sep. 30, 2012
  • miyagawa

    Sep. 28, 2012
  • masaki

    Sep. 28, 2012

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

Views

Total views

13,676

On Slideshare

0

From embeds

0

Number of embeds

1,694

Actions

Downloads

16

Shares

0

Comments

0

Likes

11

×