我想检查页面上的所有框架是否均已加载。我不太清楚这一点,部分原因是我不完全了解帧事件(特别是何时frameattached
和framenavigated
事件触发时?)。
这是我现在正在做的事情,但是我多次绑定到同一页面事件,而不是框架事件。
function waitForFrames() {
return Promise.all(page.frames().map((frame) => {
return new Promise(resolve => {
page.on('framenavigated', resolve);
});
})).then(() => {
console.log('Frames loaded');
})
.catch(e => {
console.log(e.message);
});
}
如何检查所有框架均已加载?
答案 0 :(得分:1)
Frame类的Puppeteer Documentation帮助解释框架事件:
类别:框架
页面在每个时间点都通过
page.mainFrame()
和frame.childFrames()
方法公开其当前的框架树。Frame对象的生命周期由在页面对象上调度的三个事件控制:
'frameattached'
-当框架连接到页面时触发。框架只能附加到页面一次。'framenavigated'
-在框架将导航提交到其他URL时触发。'framedetached'
-当框架与页面分离时触发。框架只能与页面分离一次。
您可以使用以下功能等待一帧(按名称):
const wait_for_frame = (page, frame_name) => {
let fulfill_promise;
const promise = new Promise(x => fulfill_promise = x);
check_frame();
return promise;
const check_frame = () => {
const frame = page.frames().find(current_frame => current_frame.name() === frame_name);
if (frame) {
fulfill_promise(frame);
} else {
page.once('frameattached', check_frame);
}
};
};
// Waiting for frame to become attached:
const frame = await wait_for_frame(page, frame_name);
// Waiting for frame to contain a certain selector:
await frame.waitForSelector(selector);
const button = await frame.$(selector);
button.click();
上面的代码段受Source的影响并从中进行了改进。
最后,您可以逐帧循环浏览和await
帧。
答案 1 :(得分:0)
使用 Grant 的解决方案时,我遇到了问题,即我正在寻找的 iFrame 有时会在页面加载后分离,然后(重新)附加和导航。在这种情况下,waitForSelector 会产生一个异常“iFrame got detached”。在我看来,出现在 page.frames() 中的框架并不能保证实际被附加。
所以我改变了他的解决方案的wait_for_frame函数来覆盖这种情况。这也包括页面上有多个 iFrame 的情况。
const wait_for_frame = (page, frame_name) => {
const check_frame = frame => {
if (frame.name() == frame_name) {
fulfill_promise(frame);
page.off('framenavigated', check_frame);
}
};
let fulfill_promise;
const promise = new Promise(x => fulfill_promise = x);
page.on('framenavigated', check_frame);
return promise;
};
// Waiting for frame to become attached:
const frame = await wait_for_frame(page, frame_name);
// Waiting for frame to contain a certain selector:
await frame.waitForSelector(selector);
const button = await frame.$(selector);
button.click();