SlideShare a Scribd company logo
1 of 60
Perl でファントムする! 改め

Wight - Phantom's
   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 with
JavaScript API. It has fast and native
support for various web standards:
DOM handling, CSS selector, JSON,
Canvas, and SVG.”
                    — http://phantomjs.org/
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/
WebKit




• Web レンダリングエンジン
 - HTML, JavaScript, … 
• Safari / Chrome
Headless
• ユーザ向けの(目に見える)インター
 フェースなし
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 ページとは別のコンテキストで実行
インストール
       _
      (  ・ω・)
    _(__つ/ ̄ ̄ ̄/
      \/   /
         ̄ ̄ ̄\ 
            \┗(^o^ )┛┗(^o^ )┛┗(^o^ )┛  ┗( ^o^)┛
              \┏┗   ┏┗   ┏┗      ┛┓
                ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄




• バイナリ
- phantomjs.org/download.html 
• brew install phantomjs
使う
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. It is
akin to Old High German wiht, meaning
a creature or thing."
キラキラネームの理由(わけ)
• 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->find('//input[@type="submit"]')->click();

 foreach ($w->find('//h3[@class="r"]/a')) {
     say ' * ', $_->text;
 }
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;
  }
$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;
  }
$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;
 }
$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;
 }
$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;
 }
$w->render($filename)
$w->evaluate($JavaScript)

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


 $w->evaluate('document.body.getBoundingClientRect()')
 # {
 #   bottom => 1363,
 #   height => 1363,
 #   left => 0,
 #   right => 1024,
 #   top => 0,
 #   width => 1024
 # }
$w->execute($JavaScript)


 $w->execute(<<'JAVASCRIPT');
   var nodes = document.querySelectorAll('img');
   [].slice.call(nodes).forEach(function () {
     …
   });
 JAVASCRIPT
 # => JSON::XS::true
$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();
•$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'), 'title';

 my $link = $wight->find('//p/a')
 $link->click;
 is $w->current_url->path, '/foo';
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 WebSocket("ws://127.0.0.1:" + this.port + "/");
 this.socket.onmessage = this.commandReceived;
Perl   PhantomJS
• $w->call($method, @args) 
 - WebSocket メッセージを送信
 - $cv->recv してじっと待つ
• main.js / browser.js 
 - 結果 (エラー) が出しだい返答
 - リンクのクリックの場合 URL が変わるまで
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 {
    my ($w, @args) = @_;
    return rand() < 0.5;
});
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')->val(23); # => '$("#foo").val(23)'

jQuery('document'); # => '$(document)'

jQuery->ajax({ method => 'POST' });
# => '$.ajax({"method":"POST"})'

• 文字列化すると jQuery の式に
• それっぽいメソッドチェーン
プロパティ/コールバック


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 })'
まとめ
• PhantomJS 
• Wight 
- スクレイピングやテストに使えます
- API と実装の紹介
github.com/motemen/Wight

More Related Content

What's hot

Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Masahiro Nagano
 
Using SockJS(Websocket) with Sencha Ext JS
Using SockJS(Websocket) with Sencha Ext JSUsing SockJS(Websocket) with Sencha Ext JS
Using SockJS(Websocket) with Sencha Ext JSKazuhiro Kotsutsumi
 
Scc2014 :jQueryの仕組みを完璧に理解する
Scc2014 :jQueryの仕組みを完璧に理解するScc2014 :jQueryの仕組みを完璧に理解する
Scc2014 :jQueryの仕組みを完璧に理解するJun Futakawa
 
忙しい人のためのBackbone.jsとAngular.js入門
忙しい人のためのBackbone.jsとAngular.js入門忙しい人のためのBackbone.jsとAngular.js入門
忙しい人のためのBackbone.jsとAngular.js入門Toshiaki Maki
 
実践Backbone.Marionette 現場の悩みと解決まで
実践Backbone.Marionette 現場の悩みと解決まで実践Backbone.Marionette 現場の悩みと解決まで
実践Backbone.Marionette 現場の悩みと解決までRyuma Tsukano
 
Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Kazunari Hara
 
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...Naoya Ito
 
Backbonejs @BuildInsiderOffline #1
Backbonejs @BuildInsiderOffline #1Backbonejs @BuildInsiderOffline #1
Backbonejs @BuildInsiderOffline #1daisuke shimizu
 
Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成krdlab
 
AWS SDK for Smalltalk
AWS SDK for SmalltalkAWS SDK for Smalltalk
AWS SDK for SmalltalkSho Yoshida
 
Androidで使えるJSON-Javaライブラリ
Androidで使えるJSON-JavaライブラリAndroidで使えるJSON-Javaライブラリ
Androidで使えるJSON-JavaライブラリYukiya Nakagawa
 
WordPressで提供するWeb API
WordPressで提供するWeb APIWordPressで提供するWeb API
WordPressで提供するWeb APIYuko Toriyama
 
20140523 jQuery基礎 (HTML5ビギナーズ)
20140523 jQuery基礎 (HTML5ビギナーズ)20140523 jQuery基礎 (HTML5ビギナーズ)
20140523 jQuery基礎 (HTML5ビギナーズ)Daisuke Yamazaki
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + PerlNaoya Ito
 
Start React with Browserify
Start React with BrowserifyStart React with Browserify
Start React with BrowserifyMuyuu Fujita
 
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpress
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpressサブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpress
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpressstudo-notoj
 

What's hot (20)

Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14Web Operations and Perl kansai.pm#14
Web Operations and Perl kansai.pm#14
 
Using SockJS(Websocket) with Sencha Ext JS
Using SockJS(Websocket) with Sencha Ext JSUsing SockJS(Websocket) with Sencha Ext JS
Using SockJS(Websocket) with Sencha Ext JS
 
Scc2014 :jQueryの仕組みを完璧に理解する
Scc2014 :jQueryの仕組みを完璧に理解するScc2014 :jQueryの仕組みを完璧に理解する
Scc2014 :jQueryの仕組みを完璧に理解する
 
忙しい人のためのBackbone.jsとAngular.js入門
忙しい人のためのBackbone.jsとAngular.js入門忙しい人のためのBackbone.jsとAngular.js入門
忙しい人のためのBackbone.jsとAngular.js入門
 
実践Backbone.Marionette 現場の悩みと解決まで
実践Backbone.Marionette 現場の悩みと解決まで実践Backbone.Marionette 現場の悩みと解決まで
実践Backbone.Marionette 現場の悩みと解決まで
 
Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~Native x Webでいいとこどり開発 ~ピグトーク~
Native x Webでいいとこどり開発 ~ピグトーク~
 
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
SmartPhone development guide with CoffeeScript + Node + HTML5 Technology, for...
 
Backbonejs @BuildInsiderOffline #1
Backbonejs @BuildInsiderOffline #1Backbonejs @BuildInsiderOffline #1
Backbonejs @BuildInsiderOffline #1
 
後期講座03
後期講座03後期講座03
後期講座03
 
Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成Scotty を利用した "ゆるふわ" Web サービス作成
Scotty を利用した "ゆるふわ" Web サービス作成
 
AWS SDK for Smalltalk
AWS SDK for SmalltalkAWS SDK for Smalltalk
AWS SDK for Smalltalk
 
Androidで使えるJSON-Javaライブラリ
Androidで使えるJSON-JavaライブラリAndroidで使えるJSON-Javaライブラリ
Androidで使えるJSON-Javaライブラリ
 
Zabbix API
Zabbix APIZabbix API
Zabbix API
 
WordPressで提供するWeb API
WordPressで提供するWeb APIWordPressで提供するWeb API
WordPressで提供するWeb API
 
2時間で学ぶjQuery
2時間で学ぶjQuery2時間で学ぶjQuery
2時間で学ぶjQuery
 
20140523 jQuery基礎 (HTML5ビギナーズ)
20140523 jQuery基礎 (HTML5ビギナーズ)20140523 jQuery基礎 (HTML5ビギナーズ)
20140523 jQuery基礎 (HTML5ビギナーズ)
 
Backbone.js入門
Backbone.js入門Backbone.js入門
Backbone.js入門
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + Perl
 
Start React with Browserify
Start React with BrowserifyStart React with Browserify
Start React with Browserify
 
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpress
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpressサブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpress
サブドメインサイト作成の手順|お名前ドットコム&さくらレンタルサーバ&Wordpress
 

Viewers also liked

Viewers also liked (9)

Network Programming With Anyevent
Network Programming With AnyeventNetwork Programming With Anyevent
Network Programming With Anyevent
 
Carton CPAN dependency manager
Carton CPAN dependency managerCarton CPAN dependency manager
Carton CPAN dependency manager
 
ZeroMQ in PHP
ZeroMQ in PHPZeroMQ in PHP
ZeroMQ in PHP
 
No Hugging, No Learning
No Hugging, No LearningNo Hugging, No Learning
No Hugging, No Learning
 
Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011Deploying Plack Web Applications: OSCON 2011
Deploying Plack Web Applications: OSCON 2011
 
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQueryRemedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
Remedie: Building a desktop app with HTTP::Engine, SQLite and jQuery
 
Tatsumaki
TatsumakiTatsumaki
Tatsumaki
 
Intro to PSGI and Plack
Intro to PSGI and PlackIntro to PSGI and Plack
Intro to PSGI and Plack
 
CPAN Realtime feed
CPAN Realtime feedCPAN Realtime feed
CPAN Realtime feed
 

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

Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)崇之 清水
 
Web制作のアレコレ
Web制作のアレコレWeb制作のアレコレ
Web制作のアレコレregret raym
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用Yatabe Terumasa
 
15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )hiro345
 
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Mori Shingo
 
TDC20111031_Groovy_Geb
TDC20111031_Groovy_GebTDC20111031_Groovy_Geb
TDC20111031_Groovy_GebNobuhiro Sue
 
HTML5の前のJavaScript入門
HTML5の前のJavaScript入門HTML5の前のJavaScript入門
HTML5の前のJavaScript入門Hiroki Toyokawa
 
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境Masashi Shinbara
 
Dive into the Cloud with our buddy, lovely PHP!
Dive into the Cloud with our buddy, lovely PHP!Dive into the Cloud with our buddy, lovely PHP!
Dive into the Cloud with our buddy, lovely PHP!Sotaro Omura
 
どこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷Javaどこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷JavaToshiaki Maki
 
bashでWebブラウザ(Selenium WebDriver)を動かした話
bashでWebブラウザ(Selenium WebDriver)を動かした話bashでWebブラウザ(Selenium WebDriver)を動かした話
bashでWebブラウザ(Selenium WebDriver)を動かした話洋史 東平
 
laravel x モバイルアプリ
laravel x モバイルアプリlaravel x モバイルアプリ
laravel x モバイルアプリMasaki Oshikawa
 
WordBench Kobe jQueryどうでしょう
WordBench Kobe jQueryどうでしょうWordBench Kobe jQueryどうでしょう
WordBench Kobe jQueryどうでしょうHishikawa Takuro
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方Fumihiko Shiroyama
 
Infrastructure as code for azure
Infrastructure as code for azureInfrastructure as code for azure
Infrastructure as code for azureKeiji Kamebuchi
 
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC WebアプリケーションPlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC WebアプリケーションKazuhiro Hara
 

Similar to Wight: Phantom’s Perl friend - YAPC::Asia 2012 (20)

Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
Node.jsとAWS入門(Elastic Beanstalk & AWS SDK for Node.js)
 
Web制作のアレコレ
Web制作のアレコレWeb制作のアレコレ
Web制作のアレコレ
 
HTML5 on ASP.NET
HTML5 on ASP.NETHTML5 on ASP.NET
HTML5 on ASP.NET
 
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
 
15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )15分でCakePHPを始める方法(Nseg 2013-11-09 )
15分でCakePHPを始める方法(Nseg 2013-11-09 )
 
Antのススメ
AntのススメAntのススメ
Antのススメ
 
Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋Node予備校 vol.1 名古屋
Node予備校 vol.1 名古屋
 
TDC20111031_Groovy_Geb
TDC20111031_Groovy_GebTDC20111031_Groovy_Geb
TDC20111031_Groovy_Geb
 
はせがわようすけ
はせがわようすけはせがわようすけ
はせがわようすけ
 
HTML5の前のJavaScript入門
HTML5の前のJavaScript入門HTML5の前のJavaScript入門
HTML5の前のJavaScript入門
 
Haikara
HaikaraHaikara
Haikara
 
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境
もう XAMPP / MAMP はいらない!
Vagrant で作る PHP 開発環境
 
Dive into the Cloud with our buddy, lovely PHP!
Dive into the Cloud with our buddy, lovely PHP!Dive into the Cloud with our buddy, lovely PHP!
Dive into the Cloud with our buddy, lovely PHP!
 
どこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷Javaどこよりも早い Spring Boot 1.2 解説 #渋谷Java
どこよりも早い Spring Boot 1.2 解説 #渋谷Java
 
bashでWebブラウザ(Selenium WebDriver)を動かした話
bashでWebブラウザ(Selenium WebDriver)を動かした話bashでWebブラウザ(Selenium WebDriver)を動かした話
bashでWebブラウザ(Selenium WebDriver)を動かした話
 
laravel x モバイルアプリ
laravel x モバイルアプリlaravel x モバイルアプリ
laravel x モバイルアプリ
 
WordBench Kobe jQueryどうでしょう
WordBench Kobe jQueryどうでしょうWordBench Kobe jQueryどうでしょう
WordBench Kobe jQueryどうでしょう
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方
 
Infrastructure as code for azure
Infrastructure as code for azureInfrastructure as code for azure
Infrastructure as code for azure
 
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC WebアプリケーションPlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション
PlayFramework 2.0 Javaと WebSocketでつくる リアルタイムMVC Webアプリケーション
 

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

Editor's Notes

  1. &amp;#x307D;&amp;#x3048;\n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. 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
  15. \n
  16. \n
  17. &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
  18. &amp;#x3082;&amp;#x3061;&amp;#x308D;&amp;#x3093; GUI &amp;#x306A;&amp;#x3057;\n
  19. &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
  20. \n
  21. \n
  22. \n
  23. \n
  24. &amp;#x3053;&amp;#x308C;&amp;#x306F;Google&amp;#x3092;&amp;#x691C;&amp;#x7D22;&amp;#x3059;&amp;#x308B;&amp;#x4F8B;&amp;#x3067;&amp;#x3059;\n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. &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
  31. \n
  32. \n
  33. 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
  34. \n
  35. \n
  36. \n
  37. &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
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. 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
  49. 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
  50. &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
  51. 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
  52. \n
  53. \n
  54. \n
  55. \n
  56. \n
  57. \n
  58. \n
  59. \n
  60. \n
  61. \n