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]