備忘録

なんとなく暇なときにでも....

php-webdriverを使用してスクレイピングをした話

久しぶりの投稿です。
あっという間に今年も終わり。

以前phpのライブラリを使用せずにwebサイトをスクレイピングする記事を投稿しました。
hchckeeer.hatenadiary.jp hchckeeer.hatenadiary.jp

これまでは、このツールを少しづつ改良しスクレイピングを行っていたのですが
このツールではjsでレンダリングされた箇所についてはうまくスクレイピングできませんでした。

調べてみるとSelenium-webdriverのphp実装用にFacebookからphp-webdriverなるソースがあるらしくそちらを利用しました。(結局ライブラリを使うことになってしまいましたが...)
github.com

  • Seleniumの導入
    $ sudo wget http://selenium-release.storage.googleapis.com/2.48/selenium-server-standalone-2.48.2.jar

  • JDK, Xvfb, Firefoxのインストール
    $ sudo yum install -y java-1.8.0-openjdk $ sudo yum install -y xorg-x11-server-Xvfb firefox
    今回はブラウザとしてfirefoxを使用します。

  • 環境変数DISPLAYの設定

$ vi ~/.bash_profile
export DISPLAY=:3

$ source ~/.bash_profile
  • Xvfb起動
    $ Xvfb :3 -screen 0 1024x768x24 &
  • SeleniumServer起動
    $ java -jar selenium-server-standalone-2.48.2.jar

準備が整ったのでとりあえずはページタイトルを取得してみます。
実行してみると複数のエラーに直面したので1つずつ解消しました。

PHP Fatal error:  Uncaught exception 'Facebook\\WebDriver\\Exception\\WebDriverCurlException' with message 'Curl error thrown for http POST to /session with params: {"desiredCapabilities":{"browserName":"firefox","platform":"ANY","firefox_profile":"UEsDBBQAAAAIAByBnUnf9RXUNAAAADIAAAAHAAAAdXNlci5qcystTi2KLyhKTdNQKkpNTEkt0itILCpO1c3P083JT0zRS81LTMpJTVHSUUhLzClO1bTmAgBQSwECAAAUAAAACAAcgZ1J3\\/UV1DQAAAAyAAAABwAAAAAAAAAAAAAAAAAAAAAAdXNlci5qc1BLBQYAAAAAAQABADUAAABZAAAAAAA="}}\n\nOperation timed out after 30240 milliseconds with 0 out of -1 bytes received'

デフォルトのタイムアウトの時間を変更してエラーを解消。
stackoverflow.com

-タイムアウトエラーの解消後に、WebDriverからFirefoxを起動する際に発生したエラー

org.openqa.selenium.firefox.NotConnectedException: Unable to connect to host 127.0.0.1 on port 7055 after 45000 ms. Firefox console output:

WebDriverのバージョンがFirefoxのバージョンに対応していないらしい
qiita.com
firefoxのバージョンを調べてみると...

firefox -v
Mozilla Firefox 45.6.0

だったので一旦30.0.0まで引き下げました。

seopt.pw

最終的なソースコードはこんな感じに...

<?php

require_once 'vendor/autoload.php';

use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;

//web driver
$host = 'http://localhost:4444/wd/hub';
$web_driver = RemoteWebDriver::create(
                                    $host,
                                    DesiredCapabilities::firefox(),
                                    60 * 10000, // Connection timeout in miliseconds
                                    60 * 10000  // Request timeout in miliseconds
                                );
$url = 'http://hchckeeer.hatenadiary.jp/';
$web_driver->get($url);
var_dump( $web_driver->getTitle() );
                            

これでページのタイトルを取得することができました。

あとは本当に取得したかったjsでレンダリングされた後の要素を指定(webdriverでは class名, id名, tag名, xpathなどで欲しい要素の指定が可能です。)して、要素を取得するだけでした。

下記コードではtag名を指定して、そのタグに含まれるattributesを取得しています。

<?php

require_once 'vendor/autoload.php';

use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverBy;

//web driver
$host = 'http://localhost:4444/wd/hub';
$web_driver = RemoteWebDriver::create(
                                    $host,
                                    DesiredCapabilities::firefox(),
                                    60 * 10000, // Connection timeout in miliseconds
                                    60 * 10000  // Request timeout in miliseconds
                                );
$url = 'http://hchckeeer.hatenadiary.jp/';
$web_driver->get($url);
$ele = $web_driver->findElement( WebDriverBy::tagName('iframe') )->getAttribute('src');
                                

導入に少し時間がかかってしまいましたが、
比較的簡単にスクレイピングができたと思います。

本日はここまで

参考 tmysz.hateblo.jp

stackoverflow.com

WebDriver API Document

Working with PHPUnit and Selenium Webdriver