我有一个非常简单的 Puppeteer使用 exposeFunction()
的脚本在 headless Chrome 中运行一些东西。
(async function(){
var log = console.log.bind(console),
puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var functionToInject = function(){
return window.navigator.appName;
}
await page.exposeFunction('functionToInject', functionToInject);
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return await functionToInject();
});
console.log(data);
await browser.close();
})()
这失败了:
ReferenceError: window is not defined
指的是注入(inject)函数。如何在 headless Chrome 中访问 window
?
我知道我可以用 evaluate()
代替,但这不适用于我动态传递的函数:
(async function(){
var log = console.log.bind(console),
puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var data = await page.evaluate(async function(){
console.log('woo I run inside a browser')
return window.navigator.appName;
});
console.log(data);
await browser.close();
})()
最佳答案
评估
函数
您可以使用evaluate
传递动态脚本。
(async function(){
var puppeteer = require('puppeteer');
const browser = await puppeteer.launch();
const page = await browser.newPage();
var functionToInject = function(){
return window.navigator.appName;
}
var data = await page.evaluate(functionToInject); // <-- Just pass the function
console.log(data); // outputs: Netscape
await browser.close();
})()
addScriptTag
和 readFileSync
您可以将该函数保存到一个单独的文件中,并使用 addScriptTag
来使用该函数。
await page.addScriptTag({path: 'my-script.js'});
或使用readFileSync
评估
。
await page.evaluate(fs.readFileSync(filePath, 'utf8'));
或者,将参数化函数作为字符串传递给 page.evaluate
。
await page.evaluate(new Function('foo', 'console.log(foo);'), {foo: 'bar'});
动态创建新函数
如何将它变成一个 runnable
函数 :D ?
function runnable(fn) {
return new Function("arguments", `return ${fn.toString()}(arguments)`);
}
上面的代码将使用提供的参数创建一个新函数。我们可以传递任何我们想要的函数。
例如下面的带有window
的函数,以及参数,
function functionToInject() {
return window.location.href;
};
也可以完美地使用 promises,
function functionToInject() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(window.location.href);
}, 5000);
});
}
并带有参数,
async function functionToInject(someargs) {
return someargs; // {bar: 'foo'}
};
用evaluate
调用所需的函数,
var data = await page.evaluate(runnable(functionToInject), {bar: "foo"});
console.log(data); // shows the location
关于node.js - 为什么我不能使用 Puppeteer 在 exposeFunction() 函数中访问 'window'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48281130/