node.js - 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
事件。
解决方案
首先,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();
})();
推荐阅读
- python - Python:将先前抓取的数据保存在数据库中(已创建)
- flutter - 将列表布尔值转换为列表字符串颤动
- javascript - 使用 redux-saga 改变购物车
- c - 如何将 void 函数内的值发送回 C 中的主函数?
- r - 验证集方法
- python - 从特定行开始函数
- typescript - 如何将我的环境变量集成到我的文件中?
- excel - 粘贴范围对象返回随机输出
- json - 值类型为“字符串”的所有名为“id”的键的输出路径
- python - 没看懂,expected shape=(None, None, 1100),发现 shape=(1, 29907, 1),对 LSTM 输入形状的困惑?(数据为基因组序列)