DEV

puppeteerでスクレイピングしてみた

puppeteerというのを使ってみました。google chromeをコマンドラインから使えるやつです。久しぶりにjQueryやってる感じで、イライラした笑 でも便利そうだし、面白かった。これを使うと、なんか色々できそうで面白い。

本家マニュアルも読んだけど、この記事ありがたかったです。結構ややこしい。。。

https://qiita.com/go_sagawa/items/85f97deab7ccfdce53eaqiita.com

サンプル

Googleの地図で新潟の焼肉屋を調べて、ランキング順に焼肉屋の情報を取得する

https://github.com/edo1z/puppeteer_studygithub.com

実行結果

puppeteer

コード

const puppeteer = require('puppeteer')
const mapUrl = 'https://www.google.co.jp/maps/search/'
const keywords = '新潟+焼肉'
const containerEl = '[data-result-index]'
const nameEl = 'h3 span'
const countEl = 'span.section-result-num-ratings'
const urlEl = 'button[data-section-id="ap"]'
const backBtnEl = 'button.section-back-to-list-button'
const main = async () => {
const browser = await puppeteer.launch()
const page = await browser.newPage()
await page.goto(mapUrl + keywords)
const shops = await getShops(page)
console.log(shops)
await browser.close()
}
const getShops = async (page) => {
await page.waitFor(containerEl, {timeout: 10000})
const divLength = (await page.$$(containerEl)).length
let shops = []
let rank = 1
for (let i = 0; i < divLength; i++) {
const divs = await page.$$(containerEl)
const shop = await getShop(page, divs[i], rank)
if (shop) {
shops.push(shop)
rank++
}
}
return shops
}
const getShop = async (page, div, rank) => {
const name = await div.$eval(nameEl, name => name.innerText)
const reviewCount = await div.$eval(countEl, count => count.innerText)
console.log(name)
const url = await getUrl(page, div)
return {
rank: rank,
name: name,
reviewCount: reviewCount.replace(/\((\d+?)\)/, '$1'),
url: url
}
}
const getUrl = async (page, div) => {
div.click()
await page.waitFor(backBtnEl, {timeout: 10000})
const url = await page.$eval(urlEl,
el => el.getAttribute('data-url')
).catch(() => null)
console.log(url)
page.click(backBtnEl)
await page.waitFor(containerEl, {timeout: 10000})
return url
}
main()