**
使用puppeteer抓取页面的的时候,或者执行自动化操作的时候,有个重要问题需要回答?如果网站是用spa做的,比如说react,怎么样才能确保网页完全加载网页,所有的渲染已经完成了?
当然, 同样的问题也是用浏览器插件。**
其实这个问题呢,还真的有很多人在讨论。stackoverflow.com/questions/5…
- 浏览器原生的几个接口
await page.goto(url, { waitUntil: 'load' });
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.goto(url, { waitUntil: 'networkidle0' });
await page.goto(url, { waitUntil: 'networkidle2' });
复制代码
load不行,只要页面一下载,这个event就会发生。
domcontentloaded: 大多数情况是可以的,目前没有碰到问题。
networkidle:这个表示网络没有活动,有网友说这个是不行的。
- 如果下面的方法不可靠,那该怎么办?
A) 方案A
监控页面上的某个元素。比如:
await page.waitForSelector('#blue-button');
复制代码
但是我的问题是:如果页面上这个元素根本就不存在呢?这个元素不是不出现,而是根据逻辑条件,JS根本就没有渲染出来这个按钮。那这样的话岂不是就卡死在了这里?
当然可以使用race解决,等待5秒后,如果实在没有出现,就表示这个元素根本没有存在。
return promiseTimeout(
page.waitForSelector(selector, { timeout: 0, visible: visible }), //disale pptr to prevent throw error...
TimeOut //if not found in 10s then resolve false!! else, resolve ElementHandle by pptr
);
复制代码
这样依然有问题:你怎么能保证5秒钟之后网页完全下载完成,而不是因为网速比较慢造成的?
B)方案B
实时监控页面大小等待完全下载完,成当然也涉及到一个超时的问题,如果超时30秒干脆就停止。
const waitTillHTMLRendered = async (page, timeout = 30000) => {
const checkDurationMsecs = 1000;
const maxChecks = timeout / checkDurationMsecs;
let lastHTMLSize = 0;
let checkCounts = 1;
let countStableSizeIterations = 0;
const minStableSizeIterations = 3;
while(checkCounts++ <= maxChecks){
let html = await page.content();
let currentHTMLSize = html.length;
let bodyHTMLSize = await page.evaluate(() => document.body.innerHTML.length);
console.log('last: ', lastHTMLSize, ' <> curr: ', currentHTMLSize, " body html size: ", bodyHTMLSize);
if(lastHTMLSize != 0 && currentHTMLSize == lastHTMLSize)
countStableSizeIterations++;
else
countStableSizeIterations = 0; //reset the counter
if(countStableSizeIterations >= minStableSizeIterations) {
console.log("Page rendered fully..");
break;
}
lastHTMLSize = currentHTMLSize;
await page.waitFor(checkDurationMsecs);
}
};
复制代码
使用方法
await page.goto(url, {'timeout': 10000, 'waitUntil':'load'});
await waitTillHTMLRendered(page)
const data = await page.content()
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END