javascript - 使用不可序列化参数的 Puppeteer exposeFunction
问题描述
我正在尝试使用执行一些复杂的 DOM 解析的第 3 方库:
/**
* // Simplified for this example
* module.exports.parse = (document) => {return document.title; }
*/
const { parse } = require('./parse.js');
当我尝试公开和评估 puppeteer 中的功能时:
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://stackoverflow.com', { waitUntil: ['domcontentloaded'] });
await page.exposeFunction('parse', (document) => {
return parse(document);
});
await page.evaluate(() => {
return window.parse(window.document);
});
我收到一个错误:
评估失败:TypeError: Converting circular structure to JSON\n at JSON.stringify ()\n at window.(anonymous function) ( puppeteer_evaluation_script :13:22)\n at puppeteer_evaluation_script :3:31
在文档的示例中,它传递了一个字符串(可以序列化)。是否有任何已知的方法来评估采用window
或document
作为其参数的 node.js 方法?
解决方案
下面解释的这种方法有点不同,因此请谨慎使用。
我们可以将脚本带到浏览器,而不是将 dom 带到节点上下文。借助 webpack 或 browserify 的强大功能是可能的。同样这样,我们不需要序列化任何循环变量。
这是最小的 webpack 配置。
const path = require("path");
module.exports = {
entry: "./browser/src.js",
output: {
path: path.resolve("browser"),
filename: "dist.js",
libraryTarget: "global"
},
module: {
rules: [
{
test: /\.js$/,
use: "babel-loader"
}
]
}
};
我们将浏览器脚本放在browser/src.js
文件夹中。然后当我们运行时webpack
,它会生成browser/dist.js
我们可以在浏览器中注入的内容。
最后我可以用以下方法之一调用它,
await page.addScriptTag({path: "./browser/dist.js"});
await page.evaluate(fs.readFileSync("./browser/dist.js", 'utf8'));
只要我们不使用任何无法捆绑的本机二进制文件,它就可以完美运行。
为简单起见,这里是其他文件,
// browser/src.js
module.exports.parse = window => {
return window.location.href;
};
// index.js
const fs = require("fs");
const puppeteer = require("puppeteer");
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.evaluate(fs.readFileSync("./browser/dist.js", 'utf8'));
const data = await page.evaluate(() => {
return parse(window);
});
console.log({ data });
})();
// The result:
{ data: 'about:blank' }
推荐阅读
- javascript - Why isn't this spread operator updating my state properly?
- javascript - How to integrate starting Sass with the node server?
- java - 我第一次离开应用程序后我的数据保存了,但第二次后它不保存了
- javascript - 过滤后返回处于 React 状态的对象的正确长度
- arrays - 尝试使用 cstrings 读取文本文件
- javascript - Discord 收集器不适合我
- python - 将类的单个实例设置为从类方法输入
- nginx - 即使在 nginx 上使用 HTTP/2,也可以使用自定义服务器名称
- python - 将参数传递给 python exe
- python - Python插入sqlite表