はじめに
- ウェブページをスクレイピングして遊んでいたところ JavaScript を使った動的なページが出てきて困ったので、Google Cloud Functions と Puppetter を使ってウェブページのダウンロードと JavaScript の実行をしてコンテンツを返してくれる API を作りました。
できたもの
つかいかた
# ダウンロード
git clone https://github.com/nirasan/cloud-functions-dynamic-page-renderer.git
# 初期化cd cloud-functions-dynamic-page-renderer
npm install# ローカルで実行
npm start &
curl -G'http://localhost:8080'--data-urlencode'url=http://example.com/'# Google Cloud Functions にデプロイ(gcloud の初期化やプロジェクトの作成は済んでいるものとする)
npm run deploy
解説
- Google Cloud Functions の nodejs8 ランタイムでは Puppetter をサポートしているので超手軽にヘッドレスブラウザを実行することが出来ます。
コンテンツのダウンロードと JavaScript の実行
- Puppetter でウェブページをダウンロードして実行するのはこんな感じでほぼサンプルみたいなものです。
index.js
asyncfunctionrun(url){constpuppeteer=require('puppeteer');constbrowser=awaitpuppeteer.launch({args:['--no-sandbox','--disable-setuid-sandbox']});constpage=awaitbrowser.newPage();awaitpage.goto(url,{waitUntil:'networkidle0'});awaitautoScroll(page);constcontent=awaitpage.content();browser.close();returncontent;}
autoScroll()
は画面をスクロールさせることで画像の遅延読み込みや JavaScript の遅延実行が行われるようにしています。
index.js
asyncfunctionautoScroll(page){awaitpage.setViewport({width:1200,height:800});awaitpage.evaluate(async()=>{awaitnewPromise((resolve,reject)=>{lettotalHeight=0;constdistance=100;consttimer=setInterval(()=>{constscrollHeight=document.body.scrollHeight;window.scrollBy(0,distance);totalHeight+=distance;if(totalHeight>=scrollHeight){clearInterval(timer);resolve();}},100);});});}
Cloud Functions 関数本体
- Cloud Functions に登録している関数本体は
run()
を実行してコンテンツを返すだけです。
index.js
exports.dynamicPageRenderer=(req,res)=>{consturl=req.query.url;if(!url){return;}run(url).then((content)=>{res.status(200).send(content);}).catch((err)=>{console.error(err);res.status(500).send("error: "+err);})};
開発サーバー立ち上げ
- ローカル実行は Functions Frameworkというのが用意されていて簡単に開発用サーバーを立ち上げることが出来ます。
functions-framework --target=dynamicPageRenderer
デプロイ
- デプロイは gcloud コマンドです。メモリは少ないと実行時に死んじゃうのでとりあえず 1GB を指定します。
gcloud functions deploy dynamicPageRenderer --runtime nodejs8 --trigger-http--memory=1024MB --timeout=120s
認証
- Cloud Functions の HTTP 関数はデフォルトで App Engine サービスアカウントなど一部の許可されたユーザーからのみアクセス可能になっています。
- ユーザーの追加や未認証ユーザーからのアクセスを受け付けたい場合は関数の設定画面から設定をします。
- 2019 年 11 月 1 日以前はデフォルトで未認証ユーザーからのアクセスを受け付けていたということで GCP 内で利用する場合はセキュアで便利になったようです。