首页 > 解决方案 > waitForNavigation 无故挂起

问题描述

我尝试单击next page按钮来迭代不同的页面,但之后click,脚本永远挂在那里,代码如下。

为什么waitForNavigation永远做不完?

async function main() {
  const br = await pptr.launch({headless: false, defaultViewport: null});
  const page = await br.newPage();

  await page.goto(
    'https://www.escentual.com/catalogsearch/result/?q=face',
    {waitUntil: 'networkidle2'}
  );

  for (var i=0; i<10; ++i) {   // click next-page button 10 times,
    await Promise.all([
      page.waitForNavigation({waitUntil: 'load', timeout: 100000}),
      page.click('#adj-nav-container > div.category-products > div.toolbar > div > div.amount > div > ol > li.next > a'),  // next-page css
    ]);
    console.log(`waited, url=${page.url()}`);
  }
  await br.close();
}

main();

标签: javascriptpuppeteer

解决方案


您尝试单击的元素顶部有一个叠加层。您应该关闭该叠加层或仅使用HTMLElement.click

page.$eval('#adj-nav-container > div.category-products > div.toolbar > div > div.amount > div > ol > li.next > a', el => el.click())

或者,您可以只更改网站 URL 中的页码:

https://www.escentual.com/catalogsearch/result/index/?p=1&q=face
https://www.escentual.com/catalogsearch/result/index/?p=2&q=face
...

检测覆盖

这是检测元素是否在覆盖层后面的一种方法。document.elementFromPoint获取坐标并返回该坐标的最顶部元素。我们使用方法获取所选元素的坐标boundingBox(),然后将其与该坐标的最顶部元素进行比较。如果它们相同,则表示该元素不在叠加层或其他元素的后面。

例子:

let targetElement = await page.$('#adj-nav-container > div.category-products > div.toolbar > div > div.amount > div > ol > li.next > a');
let {x, y} = await targetElement.boundingBox();

let isOnTop = await page.evaluate((x,y, selectedElement) => {
    let topElement = document.elementFromPoint(x,y);
    return topElement === selectedElement;
}, x, y, targetElement);

if (isOnTop)
    console.log("Element is not behind overlay");

推荐阅读