php-webdriverを使ってPHPでもSeleniumを使う方法

SeleniumといえばPythonで使うのが有名だが、PHPでも使うことができる。

php-webdriver/php-webdriver: PHP client for Selenium/WebDriver protocol. Previously facebook/php-webdriver

今回は、上記のphp-webdriverの使い方を解説していく。

php-webdriverに必要なもの

php-webdriverを使うためには以下の2つを用意する必要がある。

  • Google Chrome
  • chromedriver

php-webdriverのインストール

以下のコマンドを実行するだけ。

composer require php-webdriver/webdriver

php-webdriverを使う準備

php-webdriverを使う前にchromedriverを起動させる必要がある。

もし、サーバーであれば「Supervisor: A Process Control System — Supervisor 4.2.5 documentation」を使ってchromedriverをデーモンプロセスにしておく。

開発環境であれば、以下のコマンドでchromedriverを立ち上げておく。

chromedriver --port=4444 &

php-webdriverの使い方

php-webdriverは以下の様に使う。

<?php

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

public function setSelenium()
{
    $userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
        . " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36";

    $chromeOptions = new ChromeOptions();

    $chromeOptions->addArguments([
        "--headless=new",
        "--no-sandbox",
        "--disable-gpu",
        "--window-size=1920,1200",
        "--user-agent={$userAgent}",
    ]);

    $cap = DesiredCapabilities::chrome();
    $cap->setCapability(ChromeOptions::CAPABILITY, $chromeOptions);

    $this->driver = RemoteWebDriver::create(
        "http://localhost:4444",
        $cap
    );
}

ポイントとしては、addArgumentsメソッドの部分。 --headlessでChromeをheadlessモードで立ち上げる。

php-webdriverの処理を終えるときには、以下の処理を必ず行うこと。 そうしないと、いつまでもwebdriverがプロセスに残ってしまう。

$this->driver->quit();

要素の取得方法

$loginUrl = "https://example.com";

$this->driver->get($loginUrl);

$this->driver->findElement(WebDriverBy::cssSelector("input[type='text']"))
      ->sendKeys($loginId);

$this->driver->findElement(WebDriverBy::cssSelector("input[type='password']"))
      ->sendKeys($password);

// ログイン実行!!
$this->driver->findElement(WebDriverBy::cssSelector("button[type='submit']"))
      ->click();

ボタンをクリックできない時の対策

Chromedriverでボタンを押せない理由はいくつかあるが、「現在の画面に映っていないボタンを押そうとしている」 ことも原因の1つとしてある。

その対策としては、executeScriptメソッドを使ってJavaScript経由で画面をスクロールさせると良い。

例えば、以下の様になる

$this->driver->executeScript("window.scrollTo(0,document.body.scrollHeight);");

sleep(5);

$this->driver->findElement(WebDriverBy::cssSelector("button"))->click();

ログイン情報を保持しておきたい場合の対策

ログイン情報を保持しておきたい場合は、Chromedriverの呼び出しの引数に--user-data-dirを追加すると良い。

例えば、以下の様になる。

$chromeOptions = new ChromeOptions();

$chromeOptions->addArguments([
    "--headless=new",
    "--no-sandbox",
    "--disable-gpu",
    "--window-size=1920,1200",
    "--user-agent={$userAgent}",
    "--user-data-dir=/home/user/sample",
]);

こうすることで、/home/user/sampleディレクトリにChromeのログイン情報を保存してくれる。もし、/home/user/sampleがない場合は、自動で作ってくれる。

ポイントとしては、引数に--headless=newを追加すること。多くのwebの記事では--headlessとしているが、 Chromedriver側のバグで動かないようだ。

参考記事: Chrome’s Headless mode gets an upgrade: introducing `--headless=new` - Chrome Developers

参考文献