はじめに
larvelでテストツール(dusk)を使用し画像ショット作成。
その画像が一つに収まらない時、複数ページを取り合えす取得。
それをtcpdfで1つのpdfにしている。
chromedriverが必要とかSelenumが必要とか忘れた。
すぐに忘れるので、まだ多少動くものがあるうちにメモだけでも残す。
大まかな手順
前提:dockerを使用している
以下の環境を元に作成
Laravel DuskをDocker環境でインストールするには、いくつかのステップを踏む必要があります。以下は、そのプロセスです。
-
Laravel Duskのインストール: まず、Laravelプロジェクトのルートにあるコンテナ内でDuskをインストールします。
docker-compose exec app composer require --dev laravel/dusk
-
Duskのセットアップ: Duskをセットアップします。これには、Duskのサービスプロバイダーを登録するために、
AppServiceProvider
にコードを追加したり、Dusk専用の.env.dusk.local
環境設定ファイルを作成したりすることが含まれます。docker-compose exec app php artisan dusk:install
dusk:install
コマンドは、Duskのテストを書くためのテンプレートファイルを生成し、必要な設定ファイルをセットアップします。 -
Dockerfileの修正: DuskはデフォルトでGoogle Chromeを使用します。そのため、Dockerコンテナ内にChromeとChromeDriverをインストールする必要があります。
Dockerfile
に以下のようなコマンドを追加して、これらの依存関係をインストールします。# Chromeのインストール RUN apt-get update && apt-get install -y libnss3-dev libxss1 libasound2 libxrandr2 libatk-bridge2.0-0 libcups2 libgtk-3-0 libgbm1 # ChromeDriverのダウンロードとインストール RUN LATEST_CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \ curl -sS -o /tmp/chromedriver_linux64.zip https://chromedriver.storage.googleapis.com/$LATEST_CHROMEDRIVER_VERSION/chromedriver_linux64.zip && \ unzip /tmp/chromedriver_linux64.zip -d /usr/local/bin/ && \ chmod +x /usr/local/bin/chromedriver
Dockerfileに変更を加えたら、Dockerイメージを再ビルドする必要があります。
docker-compose up -d --build
-
Duskの実行: 環境が整ったら、Duskテストを実行してみましょう。
docker-compose exec app php artisan dusk
Duskのテスト実行時には、ブラウザがGUIモードで起動しようとするので、ヘッドレスモードで動作するように.env.dusk.local
環境ファイルを設定することを忘れないでください。たとえば、以下のような設定を行います。
Seleniumサービスの確認
-
docker-compose.yml
の確認: Seleniumサーバーをdocker-compose.yml
に追加しているか確認してください。もし追加していない場合は、以下のようにサービスを追加する必要があります。
version: '3'
services:
# 既存のサービス(app, nginx, db, ...)
selenium:
image: selenium/standalone-chrome:latest
ports:
- "4444:4444"
networks:
- laravel
# その他の必要なオプションがあれば追加する
networks:
laravel:
driver: bridge
-
ネットワークの接続確認: Seleniumサーバーが
laravel
ネットワークに接続していることを確認します。docker-compose.yml
内で他のサービスと同じネットワークに所属している必要があります。 -
コンテナの再起動: 変更を適用するために、Dockerコンテナを再起動します。
docker-compose down
docker-compose up -d
Duskの設定の確認
-
.env.dusk.local
の確認:.env.dusk.local
ファイルがプロジェクトのルートにあるか確認し、適切な設定がされているか確認してください。
APP_URL=http://localhost:8000
DUSK_DRIVER_URL=http://selenium:4444/wd/hub
Laravel Duskでテストを作成するには、artisanコマンドを使ってテストファイルを生成します。以下のコマンドをコンテナ内で実行して、新しいDuskテストファイルを作成します。
docker-compose exec app php artisan dusk:make NewExampleTest
このコマンドは、NewExampleTest
という名前で新しいDuskテストクラスを作成します。このテストクラスは tests/Browser
ディレクトリ内に配置されます。
<?php
namespace Tests\Browser;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;
class NewExampleTest extends DuskTestCase
{
/**
* A Dusk test example.
*/
public function testExample(): void
{
// $this->browse(function (Browser $browser) {
// $browser->visit('https://www.yahoo.co.jp')
// ->assertSee('Yahoo');
// // JavaScriptを実行してページの最下部へスクロール
// $browser->script('window.scrollTo(0, document.body.scrollHeight);');
// // 少し待機してからスクリーンショットを撮影
// $browser->pause(1000) // 1000ミリ秒(1秒)待機
// ->screenshot('yahoo_homepage'); // スクリーンショットを撮影
// });
// $this->browse(function (Browser $browser) {
// $browser->visit('https://www.yahoo.co.jp')
// ->maximize()
// ->screenshot('yahoo_homepage'); // スクリーンショットを撮影
// });
$this->browse(function (Browser $browser) {
// Yahoo Japanのページを開く
$browser->visit('https://www.yahoo.co.jp');
// スクロールする回数を決定する
$scrolls = 3; // 例として3回スクロールする
$scrollHeight = 1000; // 各スクロールで移動する高さ
for ($i = 0; $i < $scrolls; $i++) {
// ページをスクロールする
$browser->script("window.scrollTo(0, $scrollHeight * $i);");
// スクロール後に描画が完了するまで少し待機
$browser->pause(1000); // 1秒間待機
// スクリーンショットを撮影
$browser->screenshot("page_part_{$i}");
}
});
}
}
- Duskの実行: 上記の設定を行った後、Duskテストを再度実行します。
docker-compose exec app php artisan dusk
上記のpngを一つにする
PdfController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use TCPDF;
use Illuminate\Support\Facades\File; // これを追加します
class PdfController extends Controller
{
public function createPdfFromImages()
{
// 新しいPDFドキュメントを作成
$pdf = new TCPDF();
// ヘッダーとフッターを削除
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
// 画像ファイルの配列
// $images = [
// public_path('screenshots/page_part_0.png'),
// public_path('screenshots/page_part_1.png'),
// public_path('screenshots/page_part_2.png'),
// public_path('screenshots/yahoo_homepage.png'),
// ];
$images = [
base_path('tests/Browser/screenshots/page_part_0.png'),
base_path('tests/Browser/screenshots/page_part_1.png'),
base_path('tests/Browser/screenshots/page_part_2.png'),
base_path('tests/Browser/screenshots/yahoo_homepage.png'),
base_path('tests/Browser/screenshots/peach-1.jpg'),
];
// 各画像をPDFに追加
// foreach ($images as $image) {
// $pdf->AddPage();
// // 画像をページに挿入
// $pdf->Image($image, 15, 25, 180, 0, 'PNG');
// }
foreach ($images as $image) {
$pdf->AddPage();
// ページ全体の背景色を変える場合
$pdf->SetFillColor(0, 0, 255); // RGBで青色
// ページ全体に背景色を適用
$pdf->Rect(0, 0, $pdf->GetPageWidth(), $pdf->GetPageHeight(), 'F');
// ファイルの拡張子に基づいて形式を設定
$imageType = strtolower(pathinfo($image, PATHINFO_EXTENSION));
if ($imageType == 'jpg' || $imageType == 'jpeg') {
$imageType = 'JPG';
} elseif ($imageType == 'png') {
$imageType = 'PNG';
} // 他の画像形式も同様に追加することができます
// 画像をページに挿入
$pdf->Image($image, 15, 25, 180, 0, $imageType);
}
// PDFをファイルとして出力
$pdfFileName = public_path('screenshots/combined_images.pdf');
// ディレクトリが存在しない場合は作成する
if (!File::isDirectory(dirname($pdfFileName))) {
File::makeDirectory(dirname($pdfFileName), 0755, true, true);
}
$pdf->Output($pdfFileName, 'F');
return response()->download($pdfFileName);
}
}
web.php
use App\Http\Controllers\PdfController;
Route::get('/create-pdf', [PdfController::class, 'createPdfFromImages']);
追記
1ページに収めたい場合
ある特定の要素までスクロールさせて高さを取得。
$browser->visit('あるアドレス')
->waitFor('特定の要素', 30)
->scrollTo('特定の要素');
$height = $browser->driver->executeScript("return document.body.scrollHeight");
echo "Height: " . $height . "\n";
// ページのトップまでスクロールし直す
$browser->driver->executeScript('window.scrollTo(0, 0);');
sleep(1); // スクロール後にレンダリングを安定させるために少し待つ
$browser->resize(1920, $height)
->screenshot('yahoo_screenshot');