【PHP】指定箇所のスクリーンショットとHTMLを取得する方法

PHP

CSSセレクタやXPathで指定したページ内のノードだけのスクリーンショットを撮りつつ、指定ノード以下のHTMLだけを取得する方法の解説です。

chrome-php/chrome だけでスクレイピングしていきます。

GitHub - chrome-php/chrome: Instrument headless chrome/chromium instances from PHP
Instrument headless chrome/chromium instances from PHP - chrome-php/chrome

前提条件

  • PHP 8.2以降インストール済(Laravel11の要件)
  • Composerインストール済
  • WSL2経由のUbuntu上で作業しています。
  • chrome-php/chromeを使います
  • Google Chromeインストール済

※WSL2経由のUbuntuはデフォルトではGUIが使えません。

※スクリーンショットを撮るにはGoogle Chromeが必用です。

※▼こちらのページを参考にGoogle Chromeをインストールしてください。

WSL で Linux GUI アプリを実行する
WSL で Linux GUI アプリの実行がどのようにサポートされるかについて説明します。

※AWS EC2でもインストール可能です。(確認済)

※ロリポップのような共用サーバではインストール不可です。

これからやること

  • PHPプロジェクト新規作成
  • chrome-php/chromeインストール
  • ダミーWEBサイト立ち上げ(Laravel)
  • 指定箇所の確認
  • コード作成
  • コード実行

PHPプロジェクト新規作成

フォルダ「using-chrome」を作成し、中に入ります。

mkdir using-chrome
cd using-chrome

各種ファイル保存用のフォルダを作っておきます。

mkdir -p storage/screenshots
mkdir storage/html
mkdir src

chrome-php/chromeインストール

chrome-php/chrome をインストールします。

composer require chrome-php/chrome

ダミーWEBサイト立ち上げ(Laravel)

外部WEBサイトに迷惑を掛けないように

ダウンしても構わないダミーWEBサイトを立ち上げます。

composer create-project laravel/laravel:^11 dummy-web

「dummy-web」フォルダに入り、

Laravelのビルトインサーバーを起動します。

cd dummy-web
php artisan serve

WEBブラウザで http://localhost:8000/ にアクセスします。

Laravelのデフォルトページが表示されました。

指定箇所の確認

Laravelのデフォルトページ内にある、

「Documentation」の見出しとアイコンのある個所の

親ノードのブロックをCSSセレクターで指定することにします。

この箇所のCSSセレクターは

#docs-card-content

となります。

コード作成

「src/getScreenshotAndHtml.php」

<?php

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

use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Clip;
use HeadlessChromium\Dom\Dom;
use HeadlessChromium\Dom\Selector\CssSelector;
use HeadlessChromium\Dom\Selector\XPathSelector;
use HeadlessChromium\Page;
use headlessChromium\Utils;

// 保存先フォルダ
$storagePath = __DIR__ . '/../storage/';
$dirScreenshot = $storagePath . 'screenshots/';
$dirHtml = $storagePath . 'html/';

// URL
$url = 'http://localhost:8000/';

// セレクター(CSSセレクター、またはXPath)
$selector = '#docs-card-content';
//$selector = '//*[@id="docs-card-content"]';   // XPath

// Chromeのウィンドウサイズ
$width = 800;
$height = 600;

// Chrome起動
$browserFactory = new BrowserFactory();
$browser = $browserFactory->createBrowser([
    'windowSize' => [$width, $height],
]);

try {
    // URLへアクセス、Javascriptレンダリング完了まで待ち
    $page = $browser->createPage();
    $page->navigate($url)->waitForNavigation(Page::INTERACTIVE_TIME);
    $page->evaluate('document.documentElement.innerHTML');

    // 指定箇所の位置取得
    $position = Utils::getElementPositionFromPage(
        $page,
        new CssSelector($selector)
        //new XPathSelector($selector) // XPathのときはこちら

    );

    // 指定箇所の要素の枠指定
    $clip = new Clip(
        $position['left'],
        $position['top'],
        $position['width'],
        $position['height'] 
    );

    // スクリーンショット保存(ページ全体)
    $page->screenshot([
            'captureBeyondViewport' => true,
            'clip' => $page->getFullPageClip(),
        ])
        ->saveToFile($dirScreenshot . '/localhost_top_full_page.png');

    // スクリーンショット保存(指定要素のみ)
    $page->screenshot([
            'captureBeyondViewport' => true,
            'clip' => $clip,
        ])
        ->saveToFile($dirScreenshot . '/localhost_top_seleced.png');

    // ページ全体のHTML取得&保存
    $html = $page->getHtml();
    file_put_contents($dirHtml . 'localhost_top.html', $html);

    // 指定箇所以下のHTML取得&保存
    $selectedNodes = (new Dom($page))->search($selector);
    file_put_contents(
        $dirHtml . 'localhost_top_selected.html',
        // 複数の該当ノードのHTMLを改行コードで結合
        implode(
            PHP_EOL,
            array_map(
                // $node: HeadlessChromium\Dom\Node
                // HeadlessChromium\Dom\Node->getHtml()
                // で該当ノード以下のHTMLを文字列で取得できます。 
                fn ($node) => $node->getHtml(),

                // $selectedNodes: array<int, HeadlessChromium\Dom\Node>
                $selectedNodes
            )
        )
    );
} finally {
    // Chrome終了
    $browser->close();
}

コード実行

実行してみます。

php -f src/getScreenshotAndHtml.php

数秒経って、スクリーンショットとHTMLが保存されました。

まずはスクリーンショットを確認してみます。

▼ページ全体

▼CSSセレクターでの指定箇所

続いてHTMLを確認してみます。

▼ページ全体のHTML

▼CSSセレクターでの指定箇所のHTML

しっかりキャプチャできていますね。

  • 1
  • 0
  • 0
  • 0

コメント

タイトルとURLをコピーしました