puppeteerを使ってスクリーンキャプチャをFirebase Storageに保存する
はじめに
Nodejs環境にてFirebaseAdmin
とpuppeteer
を用いてWEBページのスクリーンショットを作成し、Firebase Storageに保存するまでの手順と注意点の覚書となります
環境
- Nodejs
使用するパッケージ
以下をnpmまたはyarnでインストール
- firebase-admin : Firebase Storageへのアップロードに使用
- puppeteer : ヘッドレスChrome環境でスクリーンキャプチャを取得するために使用
- uuid : 画像をダウンロードするためのアクセストークン付与に使用
手順
1. 初期化処理
firebaseAdmin
の初期化を行います(参考:スタートガイド)
import * as firebaseAdmin from 'firebase-admin';
firebaseAdmin.initializeApp({
credential: firebaseAdmin.credential.cert({
privateKey: '**************',
clientEmail: '**************',
projectId: '**************',
}),
storageBucket: '<BUCKET_NAME>.appspot.com'
});
export default firebaseAdmin
2. スクリーンキャプチャの作成
puppeteer
を用いてスクリーンキャプチャをメモリ上に作成します
import puppeteer from 'puppeteer'
const capture = async ()=>{
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('対象のURL', {
waitUntil : ['load', 'networkidle2']
});
// メモリ上に作成
const buffer = await page.screenshot();
await browser.close();
}
ここでの注意点としてはpage.goto
のoptionにwaitUntil : ['load', 'networkidle2']
を指定しています。この指定がなかった場合、ページによっては真っ白の状態(JS等による構築が未完)でキャプチャを作成してしまう場合があります。そのため、networkidle2
を指定することで通信処理等がアイドルになっていることを完了の目安としています。こちらの詳細についてはAPIドキュメントが詳しいです。
3. Firebase Storageへのデータ登録
メモリ上に作成したスクリーンキャプチャをFirebase Storageに登録します。
import puppeteer from 'puppeteer'
+ import firebaseAdmin from './firebaseAdmin' // 1で初期化したもの
+ import { v4 } from 'uuid';
const capture = async ()=>{
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('対象のURL', {
waitUntil : ['load', 'networkidle2']
});
const buffer = await page.screenshot();
+ const bucket = firebaseAdmin.storage().bucket('バケット名');
+ const savePath = 'Firebase Storageの保存先パス'
+ const bucketFile = bucket.file(savePath)
+ // firebaseStorageDownloadTokensはダウンロードURLを得るために必要
+ const firebaseStorageDownloadTokens = v4()
+ await bucketFile.save(buffer, {
+ metadata: {
+ contentType: 'image/png',
+ metadata: {
+ firebaseStorageDownloadTokens
+ }
+ },
+ const downloadUrl = `https://firebasestorage.googleapis.com/v0/b/バケット名/o/${encodeURIComponent(savePath)}?alt=media&token=${firebaseStorageDownloadTokens}`;
+ await browser.close();
}
ここでの注意点ですが、
metadata: {
firebaseStorageDownloadTokens
}
の記述がない場合、ファイルが正しくダウンロードできなくなります。Firebase condole上では次のように画像が延々とローディングが表示される状態となります
(参考:Firebase Storage - Image preview is permenantly loading)
また、firebaseStorageDownloadTokens
はuuid
形式の必要があるため、uuid
のライブラリを使用してトークンを作成しています
(Web版のfirebaseを用いてStorageにアップロードする場合には、このアクセストークンは自動的に付与されるようです)
その他注意事項
puppeteer
はChroniumをダウンロードする点や使用メモリを結構食う点、LambdaやCloud Functionなどの環境で実行する際には注意が必要になります
-
Running Puppeteer on AWS Lambda
- ダウンロードされるChroniumがLambdaの50MBのサイズ制限を超えてしまうため、chrome-aws-lambda 等を用いて制限を回避する必要があります
-
Running Puppeteer on Google Cloud Functions
- node10以上を指定する。また別途、Firebase Cloud Functionから実行する際にはメモリ不足でエラーとなる可能性があるため、割り当てメモリをデフォルトから変更しておくことをおすすめします
最後に
capture.ts
の全体のコードは以下のようになります
import puppeteer from 'puppeteer'
import { v4 } from 'uuid';
import firebaseAdmin from './firebaseAdmin'
const capture = async ()=>{
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('対象のURL', {
waitUntil : ['load', 'networkidle2']
});
const buffer = await page.screenshot();
const bucket = firebaseAdmin.storage().bucket('バケット名')
const savePath = 'Firebase Storageの保存先パス'
const bucketFile = bucket.file(savePath)
const firebaseStorageDownloadTokens = v4()
await bucketFile.save(buffer, {
metadata: {
contentType: 'image/png',
metadata: {
firebaseStorageDownloadTokens
}
},
})
const downloadUrl = `https://firebasestorage.googleapis.com/v0/b/バケット名/o/${encodeURIComponent(savePath)}?alt=media&token=${firebaseStorageDownloadTokens}`;
await browser.close();
}
Author And Source
この問題について(puppeteerを使ってスクリーンキャプチャをFirebase Storageに保存する), 我々は、より多くの情報をここで見つけました https://qiita.com/mktu/items/06fdc448aa21815fb988著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .