puppeteerでAmazonのレポートページに自動ログインしてSSを撮る
以前、「WSH(VBScript)でブラウザを自動操作する」でも軽く名称だけ触れていますが、Node.jsライブラリと聞くだけで何だか難しそう…とPuppeteerを敬遠していました。
ところが実際触ってみるとこれがえらく簡単な仕組みなのです。
Node.jsってなんぞやと調べてもサーバーサイドうんぬんかんぬんという説明が出てきたり、Linuxでの操作例だったりで、後回しにしていましたが、実際はWindows用のセットアッププログラムがあって次へ次へとクリックするだけで終わり。
先に全体の流れを書いておくと、
- Node.jsをセットアップ
- コマンド一発でPuppetterをインストール
- JavaScriptを書いて実行
マジでこんだけです。JavaScriptでのブラウザ自動操作に興味があるけど、Node.jsとやらがよくわからん…な人は食わず嫌いしてないで、とっととインストールすると良いよ!
WindowsへNode.jsをインストールする
一言で言うとダウンロードして実行ファイル起動して次へ次へとクリックするだけなんですけど、スクリーンショットがあったほうが安心するかもなので貼っておきます。
- Node.jsのページからセットアップ。
https://nodejs.org/ja/
左の「推奨版」でOKです。ちなみにLTSというのはLong Term Supportの略で、長期サポート、つまり安定版って感じらしい。
- Node.jsのセットアップウィザードを起動して[Next]。
- ライセンスに同意して[Next]。
- インストール場所を選んで[Next]。
- インストールする機能を聞かれるけど、そのまま[Next]。
ここで選択されているnpmはPuppeteerライブラリのインストールに使いますし、Add to PATHで環境変数PATHにnode.exeやnpm.exeのパスを通してくれるのでこのまま進めるのが便利。
- なんか追加のモジュール入れておくかって聞かれるけど、特にいらないのでそのまま[Next]。
- 準備が整ったそうなので[Install]。
- インストール完了
…………ほんとボタンクリックするだけでしょ?!www
たったこれだけでNode.jsのセットアップが完了です。
コマンドプロンプトを開き、node -vと入力してnode.jsのバージョン情報が表示されれば問題なくインストールされているってことです。
C:\>node -v v12.18.0
Puppeteerライブラリをインストールする
これまた簡単で、適当なディレクトリを作って、「npm install puppeteer」と入力するだけです。
C:\>mkdir js C:\>cd js C:\js>npm install puppeteer
> [email protected] install C:\js\node_modules\puppeteer > node install.js Downloading Chromium r756035 - 144.6 Mb [====================] 100% 0.0s Chromium (756035) downloaded to C:\js\node_modules\puppeteer\.local-chromium\win64-756035 npm WARN saveError ENOENT: no such file or directory, open 'C:\js\package.json' npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN enoent ENOENT: no such file or directory, open 'C:\js\package.json' npm WARN node No description npm WARN node No repository field. npm WARN node No README data npm WARN node No license field. + [email protected] added 46 packages from 74 contributors and audited 46 packages in 14.904s 3 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
npmコマンドを実行するとこんな画面が表示されますが、現在のディレクトリの下にnode_modulesというディレクトリが作成され、その中にPuppeteerに必要なモジュールが自動的に配置されます。
上の画面ではWARNINGが出ていますが、package.jsonがねーぞと言っているだけなので気にしなくてOK。なければないで勝手に作ってくれるし。
ブラウザ操作するJavaScriptを書く
もうPuppeteerのインストールは完了しているので、さっそくコーディングできます。
今回の例では c:\js ディレクトリの下に配置したので、そこに amazon.js という空のテキストファイルを用意し、こんな感じに書いてみます。
const puppeteer = require('puppeteer');
(async function(){
const browser = await puppeteer.launch({ headless: false});
const page = await browser.newPage();
await page.goto('https://affiliate.amazon.co.jp/home/reports');
await page.screenshot({path:'test.png'});
await browser.close();
})();
puppeteer.launch();でChromeを起動し、
browser.newPage();で新しいページを開き、
page.goto();でAmazonのレポートページを開き、
page.screenshot();でスクリーンショットを撮り、
browser.close();でChromeを終了しています。
どうでしょう。すごく簡単じゃないですか?
Puppeteerは非同期実行されないといけないルールなので、async function () { } という書き方になってしまいますが、それはそういうものと理解するだけのこと。
また、page.gotoやpage.screenshot等は非同期関数なので、awaitで実行終了を待っているだけです。
それ以外はごく普通のJavaScriptの書き方ですよね。
これを amazon.js というテキストファイルに保存し、
C:\js>node amazon.js
とコマンドラインで実行するだけでブラウザが自動的に起動してスクリーンショットを撮って終了します。同ディレクトリ内に test.png というファイルが出来ているハズ。
これだけではモノ足りない気がするので、もう少しだけブラウザ操作してみましょう。
PuppeteerでAmazonレポートページを開き自動ログインする
Puppeteerから起動されたChromeは普段使っているChromeとは別扱いなのでクッキー等は引き継がれません。そのため、普段からAmazonレポートページを開いていたとしても、「ログインしたままにする」のチェックを付けていたとしてもPuppeteerからページを開いたときは毎回普通のログイン画面になります。
なので、まずはIDとパスワードを自動入力して、[ログイン]ボタンを押す処理を書いてみましょう。
const puppeteer = require('puppeteer');
(async function(){
const browser = await puppeteer.launch({ headless: false});
const page = await browser.newPage();
await page.goto('https://affiliate.amazon.co.jp/home/reports');
await page.type('#ap_email', '[アマゾンのID]');
await page.type('#ap_password', '[アマゾンのパスワード]');
page.click('input[id="signInSubmit"]');
await page.waitForNavigation({timeout: 20000, waitUntil: "domcontentloaded"});
await page.screenshot({path:'test.png'});
await browser.close();
})();
今回追加したのはpage.goto~page.screenshotの間の4行だけ。
page.typeは指定したHTML要素に対して文字列を送ることが出来るのですが、今回は #ap_email(=IDがap_emailである要素)に対してメールアドレスを、#ap_passwordに対してパスワードを入力しています。
ちなみにquerySelectorと同じ表記が使えるので、"input[id=ap_email]"みたいな書き方でも良いハズ。
その後はpage.clickでログインボタンの押下ですね。ここでもセレクタが使えるので input[id="signInSubmit"] というように要素を指定しています。
クリックした後は長い時間がかかると思われるので、waitForNavigationの出番です。ここではtimeout値に20000ミリ秒=20秒を指定してドキュメントがロードされるのを待ちます。
残りは先述した動作と変わらず、スクリーンショットを撮って終了。
但し、動きとしてはこれで正しいのですが、たぶんAmazonでは「画像認証しろ」的な画面が出てきてうまく動作しないと思います。
なぜならAmazonのレポートページはChromeのユーザーエージェントなどを見て、botかどうかチェックしているから。そして実際Puppeteerはbotなのでw 画像認証されるのは当然とも言えます。
Puppeteerでユーザーエージェントを偽装する
でも、ぼくとしてはどうしても毎日Amazonのアソシエイト管理ページに自動ログインして、レポートを撮ってくれるbotが作りたかったんですね。
なので、ユーザーエージェントを偽装することにしましたw
(async function(){
const browser = await puppeteer.launch({ headless: false});
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36');
await page.goto('https://affiliate.amazon.co.jp/home/reports');
await page.type('#ap_email', '[アマゾンのID]');
await page.type('#ap_password', '[アマゾンのパスワード]');
page.click('input[id="signInSubmit"]');
await page.waitForNavigation({timeout: 20000, waitUntil: "domcontentloaded"});
await page.screenshot({path:'test.png', fullPage:true}});
await browser.close();
})();
変更点はわずか1行。
page.setUserAgentの部分ですね。
gotoでAmazonページを開く前にブラウザのユーザーエージェントを設定しています。
これでぼくの環境では画像認証が出なくなりましたが、いつまでもこんなザルチェックとは思えないので、とりあえずの対応といったところでしょうか。
あぁそれから、これは余談ですが、最後のpage.screenshot関数に fullPage:true オプションを付けることでブラウザに表示されていない部分も含めたスクリーンショットを撮ることが出来ます。便利ですねー。
まとめ
- 何となく敬遠していたNode.jsに手を出してみたらクリックするだけでインストールも環境設定も終わるという親切設計だった。
- しかもPuppeteerライブラリまで npm install puppeteer コマンド一発でインストールが完了。
- 試しにページを開いてスクリーンショットを撮るJavaScriptを書いてみたが、非常に簡単に動作した。
- ついでにユーザーエージェントの偽装と、ログイン処理なんかも入れてみた。
と、こんなところでしょうか。
実際はこの作業を行ったのはずいぶん前のことなので、今はスクリプトもアップグレードしており、Amazonアソシエイトの管理ページへ自動ログインして、レポートの生成ボタンをクリックして完了を待った後にZIPファイルをダウンロードし、今度はこれを自前のWebサイトにアップロードしてデータベースに格納する、なんてところまで自動化しています。
前々からこのブログでは繰り返し書いていますが、一人でいくつものWebサイトを運営するとなったら、自動化できる部分はとことん自動化していかないととても手がまわらないと思います。
それに何と言っても、自分が寝ている間もプログラムが勝手に働いてくれている、というイメージがなんだか楽しいw
どんなキーワードからこの記事へ訪れたかはわかりませんが、これを機に貴方もLet's puppeteer!