GitHub Actions上でsymfony/pantherを使ってスクレイピングしてみる

Yuki IwakamiPosted by

こんにちは!この記事はGRIPHONE Advent Calendar 2021 3日目の記事です。

PHPでWebサイトをスクレイピングしてE2Eテスト等をするための便利なライブラリであるsymfony/pantherを試してみたいと思います。また、実行環境として、こちらも便利なGitHub Actionsを利用したいと思います。

symfony/pantherのインストール

まずはsymfony/pantherをインストールします。

$ composer require symfony/panther
Using version ^1.1 for symfony/panther
./composer.json has been created
Running composer update symfony/panther
Loading composer repositories with package information
Updating dependencies
Lock file operations: 16 installs, 0 updates, 0 removals
  - Locking php-webdriver/webdriver (1.12.0)
  - Locking psr/container (1.1.2)
  - Locking psr/log (3.0.0)
  - Locking symfony/browser-kit (v5.3.4)
  - Locking symfony/deprecation-contracts (v2.5.0)
  - Locking symfony/dom-crawler (v5.3.7)
  - Locking symfony/http-client (v5.3.11)
  - Locking symfony/http-client-contracts (v2.5.0)
  - Locking symfony/panther (v1.1.1)
  - Locking symfony/polyfill-ctype (v1.23.0)
  - Locking symfony/polyfill-mbstring (v1.23.1)
  - Locking symfony/polyfill-php72 (v1.23.0)
  - Locking symfony/polyfill-php73 (v1.23.0)
  - Locking symfony/polyfill-php80 (v1.23.1)
  - Locking symfony/process (v5.3.12)
  - Locking symfony/service-contracts (v2.5.0)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 16 installs, 0 updates, 0 removals
  - Downloading psr/log (3.0.0)
  - Downloading symfony/http-client-contracts (v2.5.0)
  - Downloading symfony/polyfill-php80 (v1.23.1)
  - Downloading symfony/process (v5.3.12)
  - Downloading symfony/polyfill-php72 (v1.23.0)
  - Downloading symfony/deprecation-contracts (v2.5.0)
  - Downloading psr/container (1.1.2)
  - Downloading symfony/service-contracts (v2.5.0)
  - Downloading symfony/polyfill-php73 (v1.23.0)
  - Downloading symfony/http-client (v5.3.11)
  - Downloading symfony/polyfill-mbstring (v1.23.1)
  - Downloading symfony/polyfill-ctype (v1.23.0)
  - Downloading symfony/dom-crawler (v5.3.7)
  - Downloading symfony/browser-kit (v5.3.4)
  - Downloading php-webdriver/webdriver (1.12.0)
  - Installing psr/log (3.0.0): Extracting archive
  - Installing symfony/http-client-contracts (v2.5.0): Extracting archive
  - Installing symfony/polyfill-php80 (v1.23.1): Extracting archive
  - Installing symfony/process (v5.3.12): Extracting archive
  - Installing symfony/polyfill-php72 (v1.23.0): Extracting archive
  - Installing symfony/deprecation-contracts (v2.5.0): Extracting archive
  - Installing psr/container (1.1.2): Extracting archive
  - Installing symfony/service-contracts (v2.5.0): Extracting archive
  - Installing symfony/polyfill-php73 (v1.23.0): Extracting archive
  - Installing symfony/http-client (v5.3.11): Extracting archive
  - Installing symfony/polyfill-mbstring (v1.23.1): Extracting archive
  - Installing symfony/polyfill-ctype (v1.23.0): Extracting archive
  - Installing symfony/dom-crawler (v5.3.7): Extracting archive
  - Installing symfony/browser-kit (v5.3.4): Extracting archive
  - Installing php-webdriver/webdriver (1.12.0): Extracting archive
  - Installing symfony/panther (v1.1.1): Extracting archive
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
13 packages you are using are looking for funding.
Use the `composer fund` command to find out more!

1.1.1のバージョンのインストールが完了です。

chromedriverのインストール

まずは、mac上で開発できるように、brewを用いてインストールしておきます。symfony/pantherREADME.mdにはgeckodriverもインストールしていますが、今回は使用しないのでインストールしていません。

$ brew install chromedriver

確認したときのバージョンは96.0.4664.45になります。

スクレイピングしてスクリーンショットを撮ってみる

README.mdに書かれているサンプルコードを参考にしながら、とりあえず動くであろうソースコードを書いてみました。

<?php

use Symfony\Component\Panther\Client;

require __DIR__.'/vendor/autoload.php';

$client = Client::createChromeClient();

$crawler = $client->request('GET', 'https://tech.griphone.co.jp/');

$client->takeScreenshot('screen.png');

これで実行してみました。

すると、以下のようなポップアップが表示され、実行に失敗してしまいました。

“chromedriver”は、開発元を検証できないため開けません。
このアプリケーションにマルウェアが含まれていないことを検証できません。

このファイルは”Homebrew Cask”より今日の20:32にsites.google.comからダウンロードされました。

一度手動でchromedriverを実行しておく必要がありそうです。

インストール先は/usr/local/bin/chromedriverなので、open /usr/local/bin/などでFinderを開きます。Finderを開き、先程インストールした chromedriverを右クリックして開くを選択します。

一度実行したらOKです。もう一度実行してみましょう。

$ php test.php
$ 

エラーなく実行されました。

$ ls
README.md       composer.json   composer.lock   screen.png      test.php        vendor

そして、ちゃんとscreen.pngファイルが生成されてました。以下がscreen.pngになります。

symfony/pantherで生成されたscreen.png

お寿司が美味しそうです。

スクショ画像をSlackに投稿する

次に生成したスクリーンショットの画像をSlackに投稿してみましょう。Slackボットを作成する手順は省略しますが、Bot Scopesにfiles:writeが必要になるので注意してください。

<?php

use Symfony\Component\Panther\Client;

require __DIR__.'/vendor/autoload.php';

$client = Client::createChromeClient();

$crawler = $client->request('GET', 'https://tech.griphone.co.jp/');

$client->takeScreenshot('screen.png');


$header = [];
$header[] = 'Content-Type: multipart/form-data';
$file = new CurlFile('screen.png', 'image/png');

// Slackに投稿する
$slackApiKey = $argv[1];
$channel = $argv[2];

$postItems = [
    'token'    => $slackApiKey,
    'channels' => $channel,
    'file'     => $file,
    'title'    => 'tech.griphone.co.jp',
    'filename' => 'screen.png',
    'filetype' => 'png',
];

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FAILONERROR, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
curl_setopt($curl, CURLOPT_URL, "https://slack.com/api/files.upload");
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postItems);

$body = curl_exec($curl);
$errno = curl_errno($curl);
$error = curl_error($curl);
curl_close($curl);

先程のソースコードに対して、雑なSlackに投稿する処理を追加しました。

コマンドの第一引数にSlackボットのUser OAuth Token、第二引数に投稿先のSlackのチャンネルを渡すように実行します。

これで実行してみます。

$ php test.php [トークン(xoxb-XXXXXXXXXXXXXX)] [チャンネル名]
スクレイピングの結果をSlackに投稿

このように、Slackに投稿することができました。

GitHub Actionsで実行する

一通りの処理ができたので、次にGitHub Actionsで実行してみたいと思います。

GitHub ActionsでPHPのバージョンを固定して実行するために、shivammathur/setup-phpを利用させていただきました。

また、PHP8.1もリリースされたので、PHP8.1で実行してみましょう。GitHub Actionsのワークフロー内でphp -vを実行するとこのようにPHP 8.1.0が使われていることが確認できます。

$ php -v
PHP 8.1.0 (cli) (built: Nov 25 2021 11:25:43) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.0, Copyright (c) Zend Technologies
    with Zend OPcache v8.1.0, Copyright (c), by Zend Technologies
    with Xdebug v3.2.0-dev, Copyright (c) 2002-2021, by Derick Rethans

ワークフローのymlファイルは以下のように作成しました。

name: スクレイピング

on:
  workflow_dispatch:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: actions/checkout@v2
      uses: actions/checkout@master
    - uses: shivammathur/setup-php@v2
      with:
        php-version: 8.1
        tools: composer:v2
    - name: initialize
      run: |
        php -v
        composer install
    - name: scraping
      env:
        SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
        SLACK_BOT_CHANNEL: ${{ secrets.SLACK_BOT_CHANNEL }}
      run: |
        php test.php ${SLACK_BOT_TOKEN} ${SLACK_BOT_CHANNEL}

Bot User OAuth Tokenチャンネルはシークレットで指定するようにしてみました。(チャンネルはベタ書きでも良いかもですが)以下のようにSettingsのSecretsから登録します。

Actions secretsにSlack Botのトークン等を設定

Actionsのトリガーとして、workflow_dispatchを設定することで、手動で実行できるようにしてみました。

これを実行すると以下のように正常に実行できるかと思います。

GitHub Actionsの実行画面

さて、Slackにはどのように投稿されたでしょうか?

GitHub Actionsで実行してSlackに投稿する

おお、無事に投稿されています。しかし画像をよく見てみましょう。

GitHub Actionsで実行して投稿された画像

よく見ると一部文字が文字化けのようになっています。どうやら日本語のフォントが存在しないようです。

日本語フォントをインストールする

日本語のフォントを表示させるために、今回はipaフォントを利用させていただきました。

name: スクレイピング

on:
  workflow_dispatch:
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - name: actions/checkout@v2
      uses: actions/checkout@master
    - uses: shivammathur/setup-php@develop
      with:
        php-version: 8.1
        tools: composer:v2
    - name: initialize
      run: |
        php -v
        sudo apt install fonts-ipafont
        composer install
    - name: scraping
      env:
        SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
        SLACK_BOT_CHANNEL: ${{ secrets.SLACK_BOT_CHANNEL }}
      run: |
        php test.php ${SLACK_BOT_TOKEN} ${SLACK_BOT_CHANNEL}

途中でsudo apt install fonts-ipafontを追加して、フォントをインストールしています。

これでもう一度スクリプトを実行したいと思います。

日本語フォントをインストールして再度Slackに投稿してみる

投稿された画像をダウンロードして確認してみました。

日本語フォントが表示された

ちゃんと日本語も表示されました。

まとめ

今回、symfony/pantherを利用してGitHub Actions上で実行し、Slackにスクレイピングした結果を投稿することができました。これでE2Eテストの結果等をSlackに投稿することも簡単に実現できそうです。