はじめに
普段はVue.js, Nuxt.jsを使った開発をしているのですが、興味本位でExpressにも触れている者です。見よう見まねでpuppeteerのコードを書いていたのですが、使いやすいように改造した際、エラーが発生。解決までに時間がかかったのでメモを残します。
# エラー内容
UnhandledPromiseRejectionWarning: Error: Evaluation failed: ReferenceError: shop is not defined
原因
$$eval内の関数はchrome上で実行されるもので、この中で事前に定義した変数とか使おうとするとエラる。
とのことでevaluate内で変数を使ったのが原因っぽいです。実際リファクタ前の文字列ベタ打ちの時はエラーが起きていなかったので。
エラーが起きた時のコード
const postPrices = await page.evaluate(() => {
const prices = document.querySelectorAll(shopPrice);
let getPrices = [];
for (let price of prices) {
getPrices.push({ price: price.textContent });
}
return getPrices;
});
解決した時のコード
evaluateを使わずに下記コードで実装。変数を使っても問題なかった。ついでにオブジェクト化させて配列に入れる処理も変更。
const priceSelector = await page.$$(shop.pricePath);
const nameSelector = await page.$$(shop.namePath);
const resultArray = [];
for (let i = 0; i < priceSelector.length; i++) {
const data = {
price: await (
await priceSelector[i].getProperty("textContent")
).jsonValue(),
name: await (
await nameSelector[i].getProperty("textContent")
).jsonValue(),
};
resultArray.push(data);
}
全体のコード
const puppeteer = require("puppeteer-core");
const executablePath =
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome";
const scraping = async (shop) => {
const browser = await puppeteer.launch({
executablePath: executablePath,
slowMo: 500,
headless: false,
});
const page = await browser.newPage();
await page.setDefaultNavigationTimeout(0);
await page.goto(shop.url, {
waitUntil: "networkidle2",
});
// scraping
const priceSelector = await page.$$(shop.pricePath);
const nameSelector = await page.$$(shop.namePath);
const resultArray = [];
for (let i = 0; i < priceSelector.length; i++) {
const data = {
price: await (
await priceSelector[i].getProperty("textContent")
).jsonValue(),
name: await (
await nameSelector[i].getProperty("textContent")
).jsonValue(),
};
resultArray.push(data);
}
await browser.close();
return resultArray;
};
module.exports = { scraping };
おわりに
evaluateに変数を入れるとエラーが出るという問題に対して深掘りができず解決ではなく回避という結果になってしまったので時間がある時にevaluateの挙動について調べていきたいです。
突貫で作ったので参考にする際はリファクタした方が良いかと…とりあえずPuppeteerで発生したUnhandledPromiseRejectionWarningエラーで躓く人がいなくなれば幸いです。