首页 > 解决方案 > NodeJS 中的 Puppeteer 报告“错误:节点不可见或不是 HTMLElement”

问题描述

我正在使用 NodeJS 的“puppeteer”来测试特定的网站。在大多数情况下它似乎工作正常,但它报告的某些地方:

错误:节点不可见或不是 HTMLElement

下面的代码选择了一个在这两种情况下都在屏幕之外的链接。

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

有什么区别?两个链接都在屏幕外。

任何帮助表示赞赏,干杯,:)

示例代码

const puppeteer = require('puppeteer');

const initialPage = 'https://statsregnskapet.dfo.no/departementer';
const selectors = [
    'div[id$="-bVMpYP"] article a',
    'div[id$="-KcazEUq"] 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[0];
    await page.waitForSelector(selector);
    handles = await page.$$(selector);
    handle = handles[12]
    console.log('Clicking on: ', await page.evaluate(el => el.href, handle));
    await handle.click();  // OK

    // Click that selector 2 - fails
    selector = selectors[1];
    await page.waitForSelector(selector);
    handles = await page.$$(selector);
    handle = handles[12]
    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事件。

标签: node.jspuppeteer

解决方案


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

您需要将其更改为:

'defaultViewport' : { 'width' : width, 'height' : height }

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

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

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

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

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

此外,您忘记在handle = handles[12].

您应该将其更改为:

handle = handles[12];

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

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

await page.waitForNavigation();

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

page.setDefaultNavigationTimeout( 90000 );

再次,您忘记在 之后添加分号handle = handles[12],因此需要将其更改为:

handle = handles[12];

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

您最初的选择器试图选择仅对xs 超小屏幕(手机)可见的元素。

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

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

div[id$="-KcazEUq"] article .dfo-widget-sm a

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

await page.waitForNavigation();

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

await browser.close();

注意:您可能还想研究处理unhandledRejection错误


这是最终的解决方案:

'use strict';

const puppeteer = require( 'puppeteer' );

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

const selectors = [
    'div[id$="-bVMpYP"] article a',
    'div[id$="-KcazEUq"] 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[0];
    await page.waitForSelector( selector );
    handles = await page.$$( selector );
    handle = handles[12];
    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[1];
    await page.waitForSelector( selector );
    handles = await page.$$( selector );
    handle = handles[12];
    console.log( 'Clicking on: ', await page.evaluate( el => el.href, handle ) );
    await handle.click();

    await page.waitForNavigation();

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

推荐阅读