PHPでブラウザ自動化

※Windowsでの説明になります

# 前置
私がさくっとブラウザ自動化したいがためにまとめた記事です。
しっかり実装したい方向けではありませぬ。

# 簡単に説明
## Selenium WebDriver
ブラウザを操作するのに必要。

ブラウザごとにドライバが用意されている。
(本記事ではChrome用のChromeDriver)

ドライバに対して、HTTPリクエストすると、**ドライバはいい感じにブラウザを動かしてくれる**。

## php-webdriver
WebDriverを動かすためのライブラリ。

WebDriverにHTTPリクエストするのも手間なので、
ライブラリにやってもらうのです。

でも、PHPは公式にないので、Facebookさんが作ってくれたようです。
今回はそれを使います。

## Selenium Standalone Server
ドライバ、ライブラリ、ブラウザの相性が悪いときに使う。

php-webdriver + Chromeでは不要なはず・・。

## 関係図
```
【php-webdriver】⇒【Selenium WebDriver(ChromeDriver)】⇒【Chrome】
```

# 必要なもの
- XAMP(PHPほしいから)
- Composer(php-webdriverインストール用)
- [php-webdriver](https://github.com/facebook/php-webdriver)
- [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/downloads)

# 準備後の例
|階層１|階層２|
|:--:|:--:|
|bin||
|L|chromedriver.exe|
|php||
|L|run.php|
|vender|composerのファイル郡|
|run.bat||

```run.bat
@echo off

php php\run.php
```

```php:php/run.php
<?php
require_once __DIR__ . '/../vendor/autoload.php';

use Facebook\WebDriver\Chrome\ChromeDriver;
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;

define ('HOST', 'hoge');

run();

function run() {
    // Chromeドライバを環境変数にぶちこむ
    putenv('webdriver.chrome.driver=' . __DIR__ . '\..\bin\chromedriver.exe');

    // ブラウザ起動
    $driver = ChromeDriver::start();
    
    // 遷移
    $driver->get('https://' . HOST . '/login');

    // テキストボックス入力
    $driver->findElement(WebDriverBy::id('id'))
    ->sendKeys('email');
    
    $driver->findElement(WebDriverBy::id('password'))
    ->sendKeys('pass');
    
    // ボタン押下
    $driver->findElement(WebDriverBy::id('form_submit'))
    ->click();
    
    // タイトルがHelloを含むものになるまで待つ
    $driver->wait()->until(
        WebDriverExpectedCondition::titleContains('Hello')
    );
}
```

# php-webdriverの使い方
主なものだけ抜粋。

詳しい説明はAPI仕様書見てね。
https://facebook.github.io/php-webdriver/latest/index.html

## ブラウザ(WebDriver)起動
```php
$driver = ChromeDriver::start();
```

※以下、ドライバオブジェクトは「$driver」とする

# ChromeDriver
RemoteWebDriverを継承しているため、おもにそっちの関数。

## URIで飛ぶ
```php
$driver->get($uri);
```

## エレメントを取得
```php
$element = $driver->findElement(WebDriverBy);
```

```php:例：id「id_txt」でエレメント取得
$driver->findElement(WebDriverBy::id('id_txt'));
```

※以下、RemoteWebElementは「$element」とする

### WebDriverBy
エレメント探しに使う。

|関数|使用目的|
|:--|:--|
|className(string $class_name)|classで探す|
|id(string $id)|idで探す|
|name(string $name)|nameで探す|
|linkText(string $link_text)|linkテキストを完全一致で探す|
|partialLinkText(string $partial_link_text)|linkテキストを曖昧で探す|
|tagName(string $tag_name)|タグで探す|

## クリック
```php
$element->click();
```

## 入力
```php
$element->sendKeys('入力値');
```

## 入力クリア
```php
$element->clear();
```

## SelectBoxの選択
```php:例
$select = new WebDriverSelect($driver->findElement(WebDriverBy::id('slct_name_list')));

$select->selectByValue('たかし');
```

## サブミット
エレメントがformのとき。

```php
$element->submit();
```

## 待機
```php
$driver->wait()->until(WebDriverExpectedCondition);
```

```php：例：titleにログインが含まれたものに変わるまで待機
$driver->wait()->until(WebDriverExpectedCondition::titleContains('ログイン'));
```

### WebDriverExpectedCondition
|関数|使用目的|
|:--|:--|
|titleIs(string $title)|titleが完全一致|
|titleContains(string $title)|titleが曖昧一致|
|urlIs(string $url)|URL完全一致|
|urlContains(string $url)|URL曖昧一致|
|presenceOfElementLocated(WebDriverBy $by)|指定したエレメントがDOMに存在するか|
|visibilityOfElementLocated(WebDriverBy $by)|指定したエレメントが可視状態でDOMに存在するか|
|elementTextContains(WebDriverBy $by, string $text)|指定テキストが指定エレメントに完全一致で存在するか|
|elementTextIs(WebDriverBy $by, string $text)|指定テキストが指定エレメントに部分一致で存在するか|
|elementValueContains(WebDriverBy $by, string $text)|指定エレメントのvalueに指定値が存在するか|