如何确保页面完全加载,然后在scrape呢?

**
使用puppeteer抓取页面的的时候,或者执行自动化操作的时候,有个重要问题需要回答?如果网站是用spa做的,比如说react,怎么样才能确保网页完全加载网页,所有的渲染已经完成了?

当然, 同样的问题也是用浏览器插件。**

其实这个问题呢,还真的有很多人在讨论。stackoverflow.com/questions/5…

  1. 浏览器原生的几个接口
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:这个表示网络没有活动,有网友说这个是不行的。

  1. 如果下面的方法不可靠,那该怎么办?

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
喜欢就支持一下吧
点赞0 分享