NodeJS 中的 Puppeteer 报告“错误:节点不可见或不是 HTMLElement" [英] Puppeteer in NodeJS reports 'Error: Node is either not visible or not an HTMLElement'

查看:160
本文介绍了NodeJS 中的 Puppeteer 报告“错误:节点不可见或不是 HTMLElement"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

<块引用>

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

以下代码选择了一个在两种情况下都不在屏幕上的链接.

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

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

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

示例代码

const puppeteer = require('puppeteer');const initialPage = 'https://statsregnskapet.dfo.no​​/departementer';const 选择器 = ['div[id$="-bVMpYP"] 文章 a','div[id$="-KcazEUq"] 文章 a'];(异步() => {让选择器、句柄、句柄;常量宽度=1024,高度=1600;const browser = await puppeteer.launch({无头:假,默认视口:{ 宽度,高度}});const page = await browser.newPage();等待 page.setViewport({ width, height});page.setUserAgent('UA-TEST');//加载第一页let stat = await page.goto(initialPage, { waitUntil: 'domcontentloaded'});//单击选择器 1 - 工作正常选择器 = 选择器 [0];等待页面.waitForSelector(选择器);handles = await page.$$(selector);句柄 = 句柄 [12]console.log('点击:', await page.evaluate(el => el.href, handle));等待 handle.click();//好的//点击那个选择器 2 - 失败选择器 = 选择器 [1];等待页面.waitForSelector(选择器);handles = await page.$$(selector);句柄 = 句柄 [12]console.log('点击:', await page.evaluate(el => el.href, handle));等待 handle.click();//错误:节点不可见或不是 HTMLElement})();

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

解决方案

首先,您传递给 puppeteer.launch() 没有键,只有值.

您需要将其更改为:

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

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

你需要把这行代码改成:

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

三、函数page.setUserAgent() 返回一个 承诺,所以你需要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"] 文章 .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 选择器 = ['div[id$="-bVMpYP"] 文章 a','div[id$="-KcazEUq"] 文章 .dfo-widget-sm a'];( async() =>{让选择器;让处理;让处理;常量宽度 = 1024;常量高度 = 1600;const 浏览器 = 等待 puppeteer.launch({'defaultViewport' : { 'width' : 宽度, 'height' : 高度 }});const page = await browser.newPage();page.setDefaultNavigationTimeout(90000);await page.setViewport( { 'width' : width, 'height' : height });等待 page.setUserAgent('UA-TEST');//加载第一页let stat = await page.goto( initialPage, { 'waitUntil' : 'domcontentloaded' } );//单击选择器 1 - 工作正常选择器 = 选择器 [0];await page.waitForSelector(选择器);handles = await page.$$(选择器);句柄 = 句柄 [12];console.log('点击:', await page.evaluate( el => el.href, handle ) );等待 handle.click();//好的等待 page.waitForNavigation();//点击那个选择器 2 - 失败选择器 = 选择器 [1];await page.waitForSelector(选择器);handles = await page.$$(选择器);句柄 = 句柄 [12];console.log('点击:', await page.evaluate( el => el.href, handle ) );等待 handle.click();等待 page.waitForNavigation();等待 browser.close();})();

I'm using 'puppeteer' for NodeJS to test a specific website. It seems to work fine in most case, but some places it reports:

Error: Node is either not visible or not an HTMLElement

The following code picks a link that in both cases is off the screen.

The first link works fine, while the second link fails.

What is the difference? Both links are off the screen.

Any help appreciated, Cheers, :)

Example code

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

})();

I'm trying to emulate the behaviour of a real user clicking around the site, which is why I use .click(), and not .goto(), since the a tags have onclick events.

解决方案

First and foremost, your defaultViewport object that you pass to puppeteer.launch() has no keys, only values.

You need to change this to:

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

The same goes for the object you pass to page.setViewport().

You need to change this line of code to:

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

Third, the function page.setUserAgent() returns a promise, so you need to await this function:

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

Furthermore, you forgot to add a semicolon after handle = handles[12].

You should change this to:

handle = handles[12];

Additionally, you are not waiting for the navigation to finish (page.waitForNavigation()) after clicking the first link.

After clicking the first link, you should add:

await page.waitForNavigation();

I've noticed that the second page sometimes hangs on navigation, so you might find it useful to increase the default navigation timeout (page.setDefaultNavigationTimeout()):

page.setDefaultNavigationTimeout( 90000 );

Once again, you forgot to add a semicolon after handle = handles[12], so this needs to be changed to:

handle = handles[12];

It's important to note that you are using the wrong selector for your second link that you are clicking.

Your original selector was attempting to select elements that were only visible to xs extra small screens (mobile phones).

You need to gather an array of links that are visible to your viewport that you specified.

Therefore, you need to change the second selector to:

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

You should wait for the navigation to finish after clicking your second link as well:

await page.waitForNavigation();

Finally, you might also want to close the browser (browser.close()) after you are done with your program:

await browser.close();

Note: You might also want to look into handling unhandledRejection errors.


Here is the final solution:

'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();
})();

这篇关于NodeJS 中的 Puppeteer 报告“错误:节点不可见或不是 HTMLElement"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆