【ブラウザ操作を自動化】puppeteer 運用Tips

puppeteerの概要

  • プログラムからブラウザ操作の自動化を行えるnodeJS製ライブラリ
  • headlessChrome(GUIなし)に対応

所感

有名なスクレイピングツールとしてRubyGemのNokogiriやPython製のBeautiful Soupがあります。それらに対しpupetterはあくまでブラウザ操作のオートメーション(自動化)ツールとしての側面が強く、Web上の要素を取得したりする所謂クローラー的な用途にはあまり向いていないかなぁという印象です。

一方でできることはかなり多く、基本的なブラウザ操作以外にも利用デバイスの偽装やスクリーンショットの取得などもできます。使いこなせると相当威力を発揮しそうです。

他ツールとの比較

  • Seleniumに対してjavascriptのため実行環境を選ばない(各種クラウドサービスで動作させれるのが個人的には大きい)
  • 使いこなすにあたって非同期処理(async/await)の概念についてある程度知っておく必要がある

puppetteerの導入

まずはnpmでインストール

npm install puppeteer  

Google Cloud FunctionsよりAWS Lambdaを推奨

Cloud Functionsは公式に対応となっているが、試したところまともに動きませんでした。Lambdaに変更したところ正常に動いたのでLambdaで動かすことをお勧めします。

puppetteerを使用するにはchrome-aws-lambdaというライブラリを使用する必要があります。

#Lambdaでpuppetteerを使う場合  
npm i chrome-aws-lambda puppeteer-core  

Functionsでの不具合は調べるとかなり出てくる。。試行錯誤はしましたがまともに動きませんでした。

サンプルコード

selectorやxpathで指定したブラウザ上の要素を指定し、操作を行うことができます。ここでは割愛しますが使い方は下の記事が詳しいです。
Puppeteerのセットアップから使い方まで〜ブラウザ操作の自動化〜

・偽装

・フォームの入力

await page.type('#inputSelector',"ああああああああああ");  

既に値が入力されているフォームに新しい値を上書きしたい場合は、下のコードを追加することで対処できて便利です。

const input = await page.$('#inputSelector');  //要素を指定  
await input.click({ clickCount: 3 }) //3回クリック  
await page.type('#inputSelector',"いいいいいい");  

・値の取得

動的なコンテンツに関してはxpathが必要なので注意します

evalを用いて値を取得できます

let inputValue = await page.$eval('#selector', element => element.value);  

・遷移

ページの読み込みが完了する前に次のプログラムを実行してしまいエラーとなる場合がよくあるので気をつけましょう。基本的にはdomcontentloadedとしておけば良いです。

await page.goto("https://qiita.com/", {waitUntil: "domcontentloaded"});  

さらに万全を期したい時はこちら

await page.goto("www.sample.com", { waitUntil: ["load", "networkidle2"] });  

・クリック

クリック後別のページに切り替わるときは必ず入れましょう。ページの遷移を待ってれます。

await page.waitForNavigation({ waitUntil: 'networkidle2' });  

・ブラウザの立ち上げ

立ち上げるときには様々なオプションを付与することができます。デフォルトはheadlessモード(ウィンドウなし)になっているのでローカル環境でデバッグする際にはheadless: falseとして無効化しておくと良いでしょう。

const puppeteer = require('puppeteer');  
const browser = await puppeteer.launch({  
    headless: false,  //headlessモードを無効化  
});  
​  
const page = await browser.newPage();  //新しいタブを開く  

chrome-aws-lambdaを使う場合は

const browser = await puppeteer.launch({  
        args: chromium.args,  
        defaultViewport: chromium.defaultViewport,  
        executablePath: await chromium.executablePath,  
        headless: chromium.headless,  
    });  

GoogleCloudFunctions(個人的には非推奨)で動かす際には以下のようにオプションを付与しないと動作しません。

const browser = await puppeteer.launch({  
    args: [  
        '--no-sandbox',  
        '--disable-setuid-sandbox'  
    ]  
});  

最後までご覧いただきありがとうございました

こっちは真面目に作ってます。笑

サクっとプログラミング

iOSアプリ開発のあれこれがまとまるwebサイト