HTML を取得後に JavaScript で DOM を操作してデータを表示するようなサイトでは curl で HTML を取得しても欲しいデータを取得できない。そこで、Chrome をヘッドレスで動かして完全にレンダリングされた後のデータを取得してみた。
目的
スクレイピングするときは、Web サーバーから HTML を取得するわけだが、(1)HTML を取得 → (2)ブラウザ側の JavaScript で DOM を操作してデータを表示、のような動きをするサイトでは、通常は(1)の段階の HTML しか取得できない。
ならば、(2)の実際にブラウザに表示されてる状態の HTML をどうやって取得するかという問題を解決するのが、ヘッドレスの Chrome らしい。
ヘッドレスの Chrome とは、Chrome のウィンドウは表示しないけど、HTML の取得やレンダリング、JavaScript の動作はGUI版の Chrome と同様に行う機能らしい。
実験
実際に試してみた。
設定
Alpine Linux ベースの PHP イメージに Chrome を追加する方式で動作環境を構築する。
数々の試行錯誤の結果、以下を考慮しないと動かないようだ。
- udev を導入する
- 日本語フォントを導入する
- 一般ユーザー権限で動かす
1 | From php:7.4-alpine3.12 |
確認
Docker コンテナを起動したら、chromium-browser が実行できるを確認する。
1 | chromium-browser --version |
続けて、HTML を取得してみる。
1 | chromium-browser --headless --disable-gpu --dump-dom --no-sandbox https://www.yahoo.co.jp/ | head |
OK っぽい。以下はオプションの説明。
- --headless
- ヘッドレスで動かす
- --disable-gpu
- いずれなくなる予定のオプション
- --dump-dom
- 取得した document.body.innerHTML を標準出力に表示する
- --no-sandbox
- サンドボックス外で起動する。セキュリティが低下するけど、Docker コンテナ内ではこれをつけないと動かないっぽい?
PHP からヘッドレス Chrome を操作する
composer.json
1 | { |
PHP
Yahoo! から<title>
タグに囲まれたテキストを取ってくるサンプル。
1 |
|