52ky 发表于 2022-5-4 15:11:13

NodeJS 中的 puppeter 报告错误:节点不可见或不是 HTMLEl

问题
我用“木偶”测试特定网站。在大多数情况下,它似乎工作得很好,但它报告了几个地方:

下面的代码选择在任何一种情况下都不在屏幕上的链接。

第一个链接工作正常,而第二个链接失败。

有什么区别?

两个链接都没有出现在屏幕上。

谢谢你的帮助,

干杯,:)
const puppeteer = require('puppeteer');

const initialPage = 'https://statsregnskapet.dfo.no/departementer';
const selectors = [
    'div article a',
    'div article a'
];

(async () => {
    let selector, handles, handle;
    const width=1024, height=1600;
    const browser = await puppeteer.launch({
      headless: false,
      defaultViewport: { width, height }
    });
    const page = await browser.newPage();
    await page.setViewport({ width, height});
    page.setUserAgent('UA-TEST');

    // Load first page
    let stat = await page.goto(initialPage, { waitUntil: 'domcontentloaded'});

    // Click on selector 1 - works ok
    selector = selectors;
    await page.waitForSelector(selector);
    handles = await page.$$(selector);
    handle = handles
    console.log('Clicking on: ', await page.evaluate(el => el.href, handle));
    await handle.click();// OK

    // Click that selector 2 - fails
    selector = selectors;
    await page.waitForSelector(selector);
    handles = await page.$$(selector);
    handle = handles
    console.log('Clicking on: ', await page.evaluate(el => el.href, handle));
    await handle.click();// Error: Node is either not visible or not an HTMLElement

})();
我试图模拟真实用户在网站周围点击的行为,这就是我使用 .click() 而不是 .goto() 的原因,因为 a 标签有一个 onclick 事件.

回答
首先,传递给 defaultViewport 的 puppeteer.launch() 对象没有键,只有值。

您需要将其更改为:

'默认视口' : { '宽度' :宽度,'高度' : 高度 }

传递给 page.setViewport() 的对象也是如此。

您需要将这行代码更改为:

等待 page.setViewport( { 'width' : 宽度, 'height' : 高度 } );

第三,函数 page.setUserAgent() 返回一个 promise ,所以你需要等待这个函数:

等待 page.setUserAgent('UA-TEST');

此外,您忘记在句柄 = 句柄 之后添加分号。

您应该将其更改为:

句柄 = 句柄 ;

此外,单击第一个链接后,您无需等待导航完成( page.waitForNavigation() )。

单击第一个链接后,应添加:

等待页面.waitForNavigation();

我注意到第二页有时会挂在导航上,因此您可能会发现增加默认导航超时( page.setDefaultNavigationTimeout() )很有用:

page.setDefaultNavigationTimeout(90000);

同样,您忘记在句柄 = 句柄 之后添加分号,因此需要将其更改为:

句柄 = 句柄 ;

请务必注意,您在单击的第二个链接中使用了错误的选择器。

原来的选择器试图选择只有xs超小屏(手机)才能看到的元素。

您需要收集一组对您指定的视口可见的链接。

因此,您需要将第二个选择器更改为:

div 文章 .dfo-widget-sm a

单击第二个链接后,您还应该等待导航完成:

等待页面.waitForNavigation();

最后,您可能还想在程序完成后关闭浏览器( browser.close() ):

等待浏览器.close();

未处理的拒绝

这是最终的解决方案:
'use strict';

const puppeteer = require( 'puppeteer' );

const initialPage = 'https://statsregnskapet.dfo.no/departementer';

const selectors = [
    'div article a',
    'div article .dfo-widget-sm a'
];

( async () =>
{
    let selector;
    let handles;
    let handle;

    const width = 1024;
    const height = 1600;

    const browser = await puppeteer.launch(
    {
      'defaultViewport' : { 'width' : width, 'height' : height }
    });

    const page = await browser.newPage();

    page.setDefaultNavigationTimeout( 90000 );

    await page.setViewport( { 'width' : width, 'height' : height } );

    await page.setUserAgent( 'UA-TEST' );

    // Load first page

    let stat = await page.goto( initialPage, { 'waitUntil' : 'domcontentloaded' } );

    // Click on selector 1 - works ok

    selector = selectors;
    await page.waitForSelector( selector );
    handles = await page.$$( selector );
    handle = handles;
    console.log( 'Clicking on: ', await page.evaluate( el => el.href, handle ) );
    await handle.click();// OK

    await page.waitForNavigation();

    // Click that selector 2 - fails

    selector = selectors;
    await page.waitForSelector( selector );
    handles = await page.$$( selector );
    handle = handles;
    console.log( 'Clicking on: ', await page.evaluate( el => el.href, handle ) );
    await handle.click();

    await page.waitForNavigation();

    await browser.close();
})();



页: [1]
查看完整版本: NodeJS 中的 puppeter 报告错误:节点不可见或不是 HTMLEl