node.js+Puppeteerによる動的ページのスクレイピング
最近のかっこいいWebとかだと、どういう仕組みかは分からないけど動的にデータが作られていて、htmlソースを見てもスクレイピングできないことがよくある。
西友のお墨付きブランドのページも、なかなか洗練されている(DeNAが作ったらしい?)。だけど商品情報をスクレイピングしようとしても、ソースコードには何も書いてないから、僕が得意な普通のVBAではうまくいかない。
西友 - プライベートブランド みなさまのお墨付き | SEIYU
あれこれ悩んで数か月、ようやく解決方法が見つかった。Puppeteerという、node.jsで動かせるChromeのヘッドレスブラウザを使うといい。これはすごくて、スクレイピング以外にもスクリーンショットなども取れる。
対象ページから抽出したいタグは、普通のChromeでInspectを選ぶことで見られると思う。node.jsはよく分からなかったけど、見よう見まねでDQNコードを作って一応動いている。非同期のところが癖があって難しかった。
はじめの一歩だから、多分すっごく汚いコードなんだろうけど、何個か作りながらnode.jsのこととかちゃんと理解できたらいいなと思う。
node.jsの最新バージョン(async対応)と、puppeteerが必要
node script.jsで実行
script.js
const fs = require('fs'); const assert = require('assert'); const puppeteer = require('puppeteer'); const len = 1500; const sequential = new Array(len) .fill(1) .map((n, i) => n + i); console.log(sequential.join(',')); loop(sequential); async function loop(v) { for (let n of v) { await hoge(n); } } async function hoge(n){ const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('http://●●.●●●●●.●●.jp/#item_' + n); console.log('http://●●.●●●●●.●●.jp/#item_' + n) //await page.screenshot({path: 'example.png'}); const Names = await page.evaluate(() => { var array = []; var el = document.querySelector('div.bdr') var node = el.querySelectorAll("p.name, p.price, p.area, div.dsc, div.rating"); for(item of node){ array.push(item.innerText); } return array; }); browser.close(); //assert(fs.existsSync('example.png')); fs.appendFile('writetest.txt', n + ',' + replaceElement(Names) + '\n', function (err) { //console.log(err); }); } function replaceElement(array) { for(var i=0; i<array.length; i++){ array[i] = array[i].replace(/\r?\n/g,""); } return array; }