PhantomJS を Selenium::Remote::Driver から使う

少し前から PhantomJS を Selenium::Remote::Driver から使っている。
PhantomJS + Wight も試したけど、今のところ Selenium::Remote::Driver の方が好き。

- PhantomJS
# コマンドラインから操作できるWebKit
# 1.8 からGhost Driver(WebDriver Wire Protocolを実装したhttpd) が組み込まれた

- Selenium::Remote::Driver - search cpan org
# WebDriver Wire Protocolのクライアント
 
意外と便利なので今後も使う。


PhantomJS はソースコードからインストールすればいい。
すごく時間がかかるので寝る前にコンパイルを始めると丁度良い。

それっぽいサンプルは以下。

#!/usr/bin/env perl                                                                                                                                                           

use strict;
use warnings;
use utf8;
use autodie;
use File::Which;
use Encode qw/encode_utf8/;
use Log::Minimal qw/infof warnf/;
use Test::TCP;
use Try::Lite;
use Selenium::Remote::Driver;
use YAML;

&main();

sub main {
    my $url = "http://news.livedoor.com/";
    my $xpath = "//*[\@id=\"content\"]/div[1]/div[3]/ul/li[1]/a";
    (&scrape($url, $xpath)) ? infof "Success. ^^" : infof "Fail. orz";
    return;
}

sub scrape {
    my ($url, $xpath) = @_;
    my $bin = scalar which 'phantomjs';
    my @entities = ();
    my $is_success = 1;
    try {
        my $phantomjs = Test::TCP->new(                                                                                                                                       
            code => sub { # 空いてるポートで立ち上げる
                my $port = shift;
                exec $bin, '--webdriver', $port;
                die "cannot execute $bin: $!";
            },
        );
        my $driver = Selenium::Remote::Driver->new(
            remote_server_addr => '127.0.0.1',
            port => $phantomjs->port(),
        );
        my $res = $driver->get($url);
        my $elems = $driver->find_elements($xpath);
        foreach my $elem (@{$elems}) {
            my $link = encode_utf8($elem->get_attribute("href"));
            my $text = encode_utf8($elem->get_text);
            my %hash = (
                'text' => $text,
                'link' => $link,
            );
            push @entities, \%hash;
        }
        $driver->quit();
        print Dump \@entities,
                                                                                                                                                                              
    } '*' => sub {
        warnf($@);
        my $is_success = 0;
    };
    return $is_success;
}


サンブルの実行結果は以下。

$/tmp/phantp.pl                                                                                                       
PhantomJS is launching GhostDriver...
Ghost Driver running on port 50684
---
- link: http://news.livedoor.com/topics/detail/7579957/
  text: 北、複数ミサイル同時発射の兆候
2013-04-10T16:17:28 [INFO] Success. ^^ at ./sample.pl line 21 


日本語の文字列も取得できる。ありがたや。

Selenium::Remote::Driver 経由でアクセスするとたまに、結果を所得できずにエラーになるサイトがある。
そういう場合は PhantomJS が時間内に木を構築するのを諦めちゃうからっぽい。
解決する方法ってあるのかな。あったら試して追記する。

参考記事


- PhantomJS + Selenium::Remote::Driver でスクレイピングをこころみる - tokuhirom - 64p
-- http://blog.64p.org/entry/2013/01/09/134847


投稿者:としのり  日時:23:59:59 | コメント | トラックバック |
blog comments powered by Disqus