📅  最后修改于: 2023-12-03 15:21:06.149000             🧑  作者: Mango
在使用 Puppeteer 进行自动化测试与爬取数据时,有时候需要等待页面加载完成或某些特定操作完成后才能进行下一步操作。Puppeteer 提供了 waitFor
方法来等待页面元素的出现或完成某些特定操作,但是它只提供了默认的延迟时间,不能根据实际情况来动态修改。因此我们需要自定义一个延迟函数,实现更为灵活的等待操作。
我们可以将 waitFor
方法封装到一个自定义的函数中,在延迟的时间内不断进行轮询,直到元素出现或完成特定操作为止。具体实现代码如下所示:
/**
* 自定义延迟函数
* @param {number} delay 延迟时间,单位 ms,默认为 1000
* @param {function} condition 条件函数,需要返回 Boolean 类型
*/
async function waitFor(delay = 1000, condition) {
let time = 0;
while (true) {
if (await condition()) {
return;
}
await new Promise(resolve => setTimeout(resolve, 100));
time += 100;
if (time > delay) {
throw new Error(`Timeout after ${delay} ms.`);
}
}
}
我们可以对该函数进行一些参数的定制,如默认等待时间为 1 秒,函数返回一个 Promise 对象,如果等待超时会抛出错误。
使用该函数时,只需要将条件函数作为参数传入即可。例如,我们需要等待某个 id 为 foo
的元素出现时,可如下调用:
await waitFor(5000, async () => {
const element = await page.$('#foo');
return !!element;
});
在等待时间内,该函数会不断进行轮询,每 100ms 进行一次,直到元素出现为止。如果超时时间超过了 5 秒,会抛出错误。
下面是一个完整的示例代码,使用自定义延迟函数在页面中搜索关键词并输出结果:
const puppeteer = require('puppeteer');
async function run() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://www.baidu.com/');
const inputEl = await page.$('#kw');
await inputEl.type('Puppeteer');
const submitEl = await page.$('#su');
await submitEl.click();
await waitFor(10000, async () => {
const resultEl = await page.$('.result-op');
return !!resultEl;
});
const links = await page.$$eval('.result-op h3 a', links => links.map(link => ({
title: link.innerText,
href: link.href
})));
console.log(links);
await browser.close();
}
async function waitFor(delay = 1000, condition) {
let time = 0;
while (true) {
if (await condition()) {
return;
}
await new Promise(resolve => setTimeout(resolve, 100));
time += 100;
if (time > delay) {
throw new Error(`Timeout after ${delay} ms.`);
}
}
}
run();
自定义延迟函数可以让我们更加灵活地等待页面元素的出现或完成某些特定操作,提高测试与爬取数据的效率与准确性。将其与 Puppeteer 结合使用,可以实现更为强大的自动化测试与数据爬取功能。