PHPでChromeを操作(クロール)

滅多に環境構築しないので、やった事などをメモ。

目的

PHP & facebook-webdriver & ChromeDriver & Chrome もしくは
PHP & facebook-webdriver & Selenium & ChromeDriver & Chrome で
クロール環境を構築。

環境

CentOS 7でPHP 5.6が動作する状態。

Google Chromeのインストール

sudo yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

最新版がインストールされるのでChromeDriverを利用する場合はバージョンを確認。

google-chrome --version

日本語フォントのインストール

sudo yum install ipa-gothic-fonts ipa-mincho-fonts ipa-pgothic-fonts ipa-pmincho-fonts

Chrome の動作確認

google-chrome --headless --disable-gpu --dump-dom http://example.com/

PDFで保存する場合は --dump-dom の代わりに --print-to-pdf を追加。
rootの場合は --no-sandbox を追加しないとエラーになる。
最近のバージョンで --disable-gpu が必要なのはWindowsだけらしい。
WebGLを無効にするには --disable-software-rasterizer も必要らしいけどよく判らない。

[0525/145839.044162:ERROR:gpu_process_transport_factory.cc(1007)] Lost UI shared context.

エラーが出てるけど動作してるのでとりあえず放置。

PATHの確認

echo $PATH

composerとかをインストールするディレクトリを確認。

composerのインストール

curl -sS https://getcomposer.org/installer | php

sudo mv composer.phar /usr/local/bin

sudo chown root:root /usr/local/bin/composer.phar

インストールが終わったらバージョン確認。

composer.phar -V

facebook-webdriverのインストール

PHPのプロジェクトのディレクトリに移動。

php composer.phar require facebook/webdriver

パスが通ってるはずなのにcomposer.pharがオープンエラー。

php /usr/local/bin/composer.phar require facebook/webdriver

解決方法が分からないのでフルパスで指定。

Do not run Composer as root/super user! See https://getcomposer.org/root for details

rootの場合にwarningが出るけど処理は続行するので放置。

ChromeDriver 2.38とライブラリのインストール(Seleniumの場合も必要)

http://chromedriver.chromium.org/downloads

最新版を確認。(2018/05/18の時点でバージョン2.38)

wget https://chromedriver.storage.googleapis.com/2.38/chromedriver_linux64.zip

unzip chromedriver_linux64.zip

sudo mv chromedriver /usr/local/bin

sudo chown root:root /usr/local/bin/chromedriver


sudo yum install -y libX11 GConf2 fontconfig

 インストールが終わったらバージョン確認。

chromedriver -v

PHPから利用する場合に /usr/local/bin/chromedriver を指定する。

Selenium 3.9のインストール(ChromeDriverの場合は不要)

http://selenium-release.storage.googleapis.com/index.html

最新版を確認。(2018/05/18の時点でバージョン3.9.1)

wget https://selenium-release.storage.googleapis.com/3.9/selenium-server-standalone-3.9.1.jar

sudo mv selenium-server-standalone-3.9.1.jar /usr/local/bin

sudo chown root:root /usr/local/bin/selenium-server-standalone-3.9.1.jar

Java 8 (JDK) ランタイムのインストール

yum search java-1.8.0-openjdk

yum install java-1.8.0-openjdk

ChromeDriverの場合やインストール済みの場合は不要。

Seleniumの起動

java -jar selenium-server-standalone-3.9.1.jar

パス通ってるのにエラー。

java -jar /usr/local/bin/selenium-server-standalone-3.9.1.jar

解決方法が分からないのでフルパスで指定。

INFO - Selenium Server is up and running on port 4444

動作が確認できたら「Ctrl + C」で終了。

Seleniumの常駐起動

java -jar /usr/local/bin/selenium-server-standalone-3.9.1.jar &

終了する場合は「ps -ef」で探して「kill (PIDを指定)」で終了。

ソース(test.php)

<?php

require_once(__DIR__ . '/vendor/autoload.php');

use Facebook\WebDriver\Chrome\ChromeDriver;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Exception\WebDriverException;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\RemoteWebElement;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;

// ChromeDriver & facebook-webdriver
function testChromeDriver()
{
	$width    = 400;
	$height   = 400;
	// 環境変数
	putenv('webdriver.chrome.driver=/usr/local/bin/chromedriver');

	try
	{
		// 非表示設定で起動
		$option = new ChromeOptions();
		$option->addArguments([
//				'--no-sandbox',	// rootの場合に必須
				'--headless',
				'--disable-gpu',
				('--window-size=' . $width . ',' . $height),	// 非表示でもスクリーンショットのサイズに反映
			]);
		$chrome = DesiredCapabilities::chrome();
		$chrome->setCapability(ChromeOptions::CAPABILITY, $option);
		$driver = ChromeDriver::start($chrome);

		// デフォルト設定で起動
//		$driver = ChromeDriver::start();

		// googleに移動
		$driver->get('https://www.google.co.jp/');
		// <input id="lst-ib" > に対して 'ChromeDriverでクロール' を入力して検索
		$driver->findElement(WebDriverBy::id('lst-ib'))->sendKeys('ChromeDriverでクロール')->submit();
		// タイムアウト10秒でタイトルを監視
		$driver->wait(10)->until(
			WebDriverExpectedCondition::titleIs('ChromeDriverでクロール - Google 検索')
		);
		// タイトルを確認
		if ($driver->getTitle() === 'ChromeDriverでクロール - Google 検索')
		{
			// スクリーンショット
			$driver->takeScreenshot(__DIR__ . '/' . __METHOD__ . '_' . __LINE__ . '.png');
		}

		// 終了
		$driver->quit();
	}
	catch (Exception $e)
	{
		var_dump($e);
	}
}

// Selenium & facebook-webdriver
function testSelenium()
{
	$width    = 400;
	$height   = 400;
	$selenium = 'http://localhost:4444/wd/hub';

	try
	{
		// 非表示設定で起動
		$option = new ChromeOptions();
		$option->addArguments([
//				'--no-sandbox',	// rootの場合に必須
				'--headless',
				'--disable-gpu',
				('--window-size=' . $width . ',' . $height),	// 非表示でもスクリーンショットのサイズに反映
			]);
		$chrome = DesiredCapabilities::chrome();
		$chrome->setCapability(ChromeOptions::CAPABILITY, $option);
		$driver = RemoteWebDriver::create($selenium, $chrome);

		// デフォルト設定で起動
//		$driver = RemoteWebDriver::create($selenium, DesiredCapabilities::chrome());

		// googleに移動
		$driver->get('https://www.google.co.jp/');
		// <input id="lst-ib" > に対して 'Seleniumでクロール' を入力して検索
		$driver->findElement(WebDriverBy::id('lst-ib'))->sendKeys('Seleniumでクロール')->submit();
		// タイムアウト10秒でタイトルを監視
		$driver->wait(10)->until(
			WebDriverExpectedCondition::titleIs('Seleniumでクロール - Google 検索')
		);
		// タイトルを確認
		if ($driver->getTitle() === 'Seleniumでクロール - Google 検索')
		{
			// スクリーンショット
			$driver->takeScreenshot(__DIR__ . '/' . __METHOD__ . '_' . __LINE__ . '.png');
		}

		// 終了、close()だとセッションが残る
		$driver->quit();
	}
	catch (Exception $e)
	{
		var_dump($e);
	}
}

// 実行
testChromeDriver();

// 実行
testSelenium();

vendorフォルダと同じ階層にtest.phpで保存。
Windowsで編集する場合に文字コードが間違ってるとsendKeys()でエラーになる。

PHP実行

php test.php

ソースと同じ場所に画像が2枚作成されていれば成功。
パーミッション次第では画像が作成できないので注意。

Failed connect to localhost:4444; Connection refused' in /作業ディレクトリ/vendor/facebook/webdriver/lib/Remote/HttpCommandExecutor.php:292

Seleniumを起動していないとエラーになるのでChromeDriverの方が良さそう。

この記事が気に入ったらサポートをしてみませんか?