Dockerでpuppeteerを動かしてフォーム予約をする
やりたいこと
結婚式に参列している最中にブラウザから申込フォームの操作をしなければいけなくなったので
crontabを使って指定日時にDockerを立ち上げ、puppeteerを操作して華麗に予約を遂行する
作業ディレクトリの作成
mkdir -p yoyaku/app/script cd yoyaku
ディレクトリ構成
yoyaku/ ├ app/ | └ script/ | └yoyaku.js └ Dockerfile
Dockerfile
FROM node:9.2.0 RUN apt-get update \ && apt-get install -y \ gconf-service \ libasound2 \ libatk1.0-0 \ libc6 \ libcairo2 \ libcups2 \ libdbus-1-3 \ libexpat1 \ libfontconfig1 \ libgcc1 \ libgconf-2-4 \ libgdk-pixbuf2.0-0 \ libglib2.0-0 \ libgtk-3-0 \ libnspr4 \ libpango-1.0-0 \ libpangocairo-1.0-0 \ libstdc++6 \ libx11-6 \ libx11-xcb1 \ libxcb1 \ libxcomposite1 \ libxcursor1 \ libxdamage1 \ libxext6 \ libxfixes3 \ libxi6 \ libxrandr2 \ libxrender1 \ libxss1 \ libxtst6 \ ca-certificates \ fonts-liberation \ libappindicator1 \ libnss3 \ lsb-release \ xdg-utils \ wget RUN mkdir -p /puppeteer/app/script WORKDIR /yoyaku/app # ローカルからコンテナへ実行ファイルが入ったディレクトリをコピー COPY app/script /yoyaku/app/script RUN npm install puppeteer # スクリーンショットをとるときに文字化けしないようフォントをインストール RUN mkdir /noto ADD https://noto-website.storage.googleapis.com/pkgs/NotoSansCJKjp-hinted.zip /noto WORKDIR /noto RUN apt-get install -y unzip RUN unzip NotoSansCJKjp-hinted.zip && \ mkdir -p /usr/share/fonts/noto && \ cp *.otf /usr/share/fonts/noto && \ chmod 644 -R /usr/share/fonts/noto/ && \ fc-cache -fv WORKDIR / RUN rm -rf /noto #実行するコマンド ENTRYPOINT ["node","/yoyaku/app/script/yoyaku.js"]
参考にした記事(ありがとうございます) qiita.com morizyun.github.io
yoyaku.js
const puppeteer = require('puppeteer'); const targetUrl = "http://hogehoge.com"; //スリープ用の関数定義 async function sleep(mSec) { return new Promise(resolve => setTimeout(resolve, mSec)); } (async () => { const browser = await puppeteer.launch({ args: [ '--no-sandbox', '--disable-setuid-sandbox' ] }); const page = await browser.newPage(); //ページ移動 await page.goto(targetUrl); //以下よく使いそうな処理の例 //-------------------ここから------------------- //dialogが出てきたら承認する page.on('dialog', async dialog => { console.log(dialog.message()); await dialog.accept(); }); //要素のクリック + 遷移がある場合は読み込みを待つ page.click('#セレクタ'); await page.waitForNavigation({timeout: 60000, waitUntil: "domcontentloaded"}); //文字入力(セレクトボックスの選択などもできる) await page.type('input[name="セレクタ"]', '入力したい文字'); //要素のvalue取得 var value = await page.$eval('#セレクタ', item =>{ return item.textContent; }) //ログ出力 console.log("なんか識別用の文字", 変数名); //スリープ(上部で定義した関数呼び出し) await sleep(5000); //スクリーンショット(実行ディレクトリに保存される) await page.screenshot({ path: '画像名' }); //処理を抜ける process.exit(); //-------------------ここまで------------------- browser.close(); })();
build
docker build -t yoyaku:latest .
最後の『.』はカレントディレクトリのDockerfileを意味する
run
docker run --rm -it -v `pwd`/app/script:/yoyaku/app/script -w /yoyaku/app/script yoyaku:latest
『-v』でローカルとコンテナ内をマウントする(コンテナ内で保存したスクリーンショットを残すため)
『-w』でワーキングディレクトリを指定する
備考
crontabで設定するときはdocker runコマンドの『-it』をとらないとエラーになる