ダメ人間オンライン

あまり信用しないほうがいい技術メモとか備忘録とかその他雑記

Puppeteerが強い💪💪💪

github.com

ヘッドレスChromeでスクレイピングが簡単にできる時代がきました。
スクロールしたら追加でコンテンツを読み込んで〜みたいなページをスクレイピングしたい機運がちょうど高まってたのでPuppeteer使ってみたんですがめっちゃ簡単に実現できて完全に最高だった。

ローカル(mac)でもサーバー(CentOS8)でも動かすの楽だったし環境によって困るみたいなこともなかった。
CentOS6で動かすのは相当大変というかほぼ無理では?という感じなのでおとなしくCentOS7or8で楽に動かしましょう。他のOSは知りません。

インストールとか動かし方とかは調べたら大量に出てくるのでそちらを見るのがいいでしょう。
簡単なサンプルと注意点だけ載せておきます。

特定のwebサイトにアクセスしてちょっとだけスクロールしてからコンテンツ取得してログに出す。実際はDBに書き込むなりどこかにPOSTしたりとかやってるけどそれは省略。

const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const device = devices['iPhone 6']; // スマートフォン用のページを表示させたい時とか指定できるよ

(async () => {
    const browser = await puppeteer.launch({
        headless: true // false にすると実際にChromeが起動してデバッグやりやすいよ
    })
    const page = await browser.newPage()
    try {
        await page.emulate(device)

        // これは sample url なのでスクロールしても何も要素追加されないよ
        await page.goto('https://blog.dameninngenn.com', {waitUntil: "domcontentloaded"})

        // 雑にスクロールさせるよ
        await page.evaluate( () => {
            window.scrollBy(0, 2000);
        });
        await page.waitFor(1000)

        // 欲しい要素見つけてテキストだけとるよ
        var item = await page.$('.footer-address > a');
        var itemText = await (await item.getProperty('textContent')).jsonValue();
        console.log(itemText);
    } catch (e) {
        console.error(e);
    } finally {
        // 必ず閉じよう!!!!!!!!!!!!!!!!!!!!!!!
        await browser.close()
    }
})()

すごい雑なコードだけど雑にやっても良い感じにできる。
1つだけ注意しないといけないことがあって、必ず try-catch で包んで finally で必ず browser.close() すること。
browser.close() しないとプロセスが残ったままになってしまう。
こうやって書いたコードを daemon 化して動かしたり cron で動かしたりすることもあると思うんですがそれでうっかり browser.close() せず抜けてしまうようになってると無限に chrome プロセスが作られて残ったままになってリソースを食い潰して地獄みたいになります。