提问人:alexc 提问时间:6/27/2018 最后编辑:Vishwanathalexc 更新时间:10/3/2023 访问量:16697
使用 puppeteer 返回窗口对象
Return window object using puppeteer
问:
我正在尝试从页面返回整个窗口对象,然后在 puppeteer 之外遍历该对象。
我正在尝试访问 Highcharts 属性中的数据,我需要访问窗口对象。普通的 javascript 代码类似于 .window.Highcharts.charts[0].series[0].data
我认为最简单的方法是使用 Puppeteer 访问该站点,然后将 Windows 对象发回给我,然后我就可以像任何其他 JS 对象一样在 puppeteer 之外使用它。
阅读文档后,我发现很难返回该对象,因为只需将“窗口”放入 chrome 控制台即可显示。我不确定我错过了什么?
我已经通读了文档,以下两种方法似乎应该有效?
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.example.com', {waitUntil: 'networkidle2'});
// METHOD 1
// Create a Map object
await page.evaluate(() => window.map = new Map());
// Get a handle to the Map object prototype
const mapPrototype = await page.evaluateHandle(() => Map.prototype);
// Query all map instances into an array
const mapInstances = await page.queryObjects(mapPrototype);
console.log(mapInstances);
await mapInstances.dispose();
await mapPrototype.dispose();
// METHOD 2
const handle = await page.evaluateHandle(() => ({window, document}));
const properties = await handle.getProperties();
const windowHandle = properties.get('window');
const documentHandle = properties.get('document');
var result = await page.evaluate(win => win, windowHandle);
console.log(result)
await handle.dispose();
await browser.close();
})();
但是,它只在控制台中返回以下内容,而不是我想要的简单对象;
不确定我是否以正确的方式处理此事,因此非常感谢任何帮助/建议。
答:
我遇到了同样的问题,我遇到了时间问题,因为 Puppeteer 与页面异步交互。将 waitForFunction 添加到页面对我有用。
await page.waitForFunction(() => window.objectOnMyWindow !== undefined);
const objectOnMyWindow = await page.evaluate(() => window.objectOnMyWindow);
“将窗口返回到 Node”是一个 XY 问题。无法返回窗口,因为它是一个复杂的、不可序列化的、具有循环引用的海量数据结构。当您尝试从中返回它时,Puppeteer 基本上会调用它,这在我所知道的任何浏览器中都不起作用。JSON.stringify(window)
evaluate()
如果您尝试从恰好附加到窗口的对象中提取数据,则可以在浏览器中执行此操作,然后将您关心的窗口的可序列化小子集返回给 Node。下面是一个概念证明:
const puppeteer = require("puppeteer"); // ^21.0.2
const html = `<!DOCTYPE html><html><body>
<script>
setTimeout(() => {
window.Highcharts = {
charts: [{series: [{data: "hello world"}]}]
};
}, 3000); // add the variable sometime after page load
</script>
</body></html>`;
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setContent(html);
const data = await page.evaluate(`
window.Highcharts.charts[0].series[0].data
`);
console.log(data); // => hello world
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
假设此数据在页面加载中不可用。你可以通过等待某个元素出现来阻止它,或者直接用 :waitForElement
waitForFunction
const html = `<!DOCTYPE html><html><body>
<script>
setTimeout(() => {
window.Highcharts = {
charts: [{series: [{data: "hello world"}]}]
};
}, 3000); // add the variable sometime after page load
</script>
</body></html>`;
let browser;
(async () => {
browser = await puppeteer.launch();
const [page] = await browser.pages();
await page.setContent(html);
await page.waitForFunction(`
window?.Highcharts?.charts[0]?.series[0]?.data
`);
const data = await page.evaluate(`
window.Highcharts.charts[0].series[0].data
`);
console.log(data); // => hello world
})()
.catch(err => console.error(err))
.finally(() => browser?.close());
评论