Puppeteer でpage.evaluate()
関数に変数を渡そうとしていますが、次の非常に簡単な例を使用すると、変数evalVar
は未定義です。
私はPuppeteerが初めてで、ビルドするサンプルが見つからないため、その変数をpage.evaluate()
関数に渡して、内部で使用できるようにする必要があります。
const puppeteer = require('puppeteer');
(async() => {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const evalVar = 'WHUT??';
try {
await page.goto('https://www.google.com.au');
await page.waitForSelector('#fbar');
const links = await page.evaluate((evalVar) => {
console.log('evalVar:', evalVar); // appears undefined
const urls = [];
hrefs = document.querySelectorAll('#fbar #fsl a');
hrefs.forEach(function(el) {
urls.Push(el.href);
});
return urls;
})
console.log('links:', links);
} catch (err) {
console.log('ERR:', err.message);
} finally {
// browser.close();
}
})();
次のように、変数をpageFunction
への引数として渡す必要があります。
const links = await page.evaluate((evalVar) => {
console.log(evalVar); // should be defined now
…
}, evalVar);
引数はシリアル化することもできます: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args 。
便利と読みやすいなので、このスタイルに固執することをお勧めします。
let name = 'jack';
let age = 33;
let location = 'Berlin/Germany';
await page.evaluate(({name, age, location}) => {
console.log(name);
console.log(age);
console.log(location);
},{name, age, location});
次の構文を使用して、1つの変数を page.evaluate()
に渡すことができます。
await page.evaluate(example => { /* ... */ }, example);
注:複数の変数を渡す場合を除き、変数を
()
で囲む必要はありません。
次の構文を使用して、複数の変数を page.evaluate()
に渡すことができます。
await page.evaluate((example_1, example_2) => { /* ... */ }, example_1, example_2);
注:変数を
{}
で囲む必要はありません。
function
を渡すには、2つの方法があります。
// 1. Define in evaluationContext
await page.evaluate(() => {
window.yourFunc = function() {...};
});
const links = await page.evaluate(() => {
const func = window.yourFunc;
func();
});
// 2. Transform function to serializable. (Function can not be serialized)
const yourFunc = function() {...};
const obj = {
func: yourFunc.toString()
};
const links = await page.evaluate((obj) => {
const funStr = obj.func;
const func = new Function(`return ${funStr}.apply(null, arguments)`)
func();
}, obj);
console.log()
のevaluate()
がノードコンソールに表示できないことを理解するのにかなり時間がかかりました。
参照: https://github.com/GoogleChrome/puppeteer/issues/1944
page.evaluate関数内で実行されるすべては、ブラウザーページのコンテキストで実行されます。スクリプトはnode.jsではなくブラウザで実行されているため、ログを記録するとブラウザコンソールに表示され、ヘッドレスで実行している場合は表示されません。関数内にノードブレークポイントを設定することもできません。
これが役立つことを願っています。