代码之家  ›  专栏  ›  技术社区  ›  avocado

无缘无故的等待航行

  •  0
  • avocado  · 技术社区  · 4 年前

    我试着点击 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();
    
    0 回复  |  直到 4 年前
        1
  •  1
  •   mbit    4 年前

    您要单击的元素顶部有一个覆盖。你要么关闭覆盖层,要么使用 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");