我正在使用NodeJS的“puppeteer”来测试一个特定的网站。在大多数情况下,它似乎工作正常,但它报告了一些地方:
错误:节点不可见或不是HTMLElement
下面的代码选取了一个在两种情况下都不在屏幕上的链接。
第一个链接工作正常,而第二个链接出现故障。
有什么区别吗?两个链接都不在屏幕上。
感谢任何帮助,干杯,:)
示例代码
const puppeteer = require('puppeteer');
const initialPage = 'https://website.com/path';
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
事件。
5条答案
按热度按时间7y4bm7vi1#
而不是
这样做:
这告诉浏览器在给定元素上运行JavaScript
HTMLElement.click()
方法,即使该元素被隐藏,屏幕外或被其他元素覆盖,也会在该元素上触发click
event,而button.click()
使用Puppeteer的ElementHandle.click()
,它可以在该元素上运行HTMLElement.click()
。1.滚动页面直到元素在视图中
1.获取元素的边界框(这一步是错误发生的地方),并计算该框中间的屏幕 x 和 y 像素坐标
1.将虚拟鼠标移动到这些坐标,并将鼠标设置为“向下”,然后返回到“向上”,这将触发鼠标下的元素上的单击事件
velaa5lx2#
首先,传递给
puppeteer.launch()
的defaultViewport
对象没有键,只有值。您需要将其更改为:
传递给
page.setViewport()
的对象也是如此。您需要将这行代码更改为:
第三,函数
page.setUserAgent()
返回一个promise
,所以你需要await
这个函数:此外,您忘记在
handle = handles[12]
之后添加分号。您应该将其更改为:
此外,您不必在单击第一个链接后等待导航完成(
page.waitForNavigation()
)。点击第一个链接后,您应该添加:
我注意到第二个页面有时会挂起导航,所以你可能会发现增加默认导航超时(
page.setDefaultNavigationTimeout()
)很有用:又一次,您忘记在
handle = handles[12]
后面添加分号,因此需要将其更改为:重要的是要注意,您正在为您单击的第二个链接使用错误的选择器。
您的原始选择器试图选择仅对
xs
extra small 屏幕(移动的电话)可见的元素。您需要收集指定视口可见的链接数组。
因此,您需要将第二个选择器更改为:
您也应该在单击第二个链接后等待导航完成:
最后,您可能还希望在完成程序后关闭浏览器(
browser.close()
):**注意:**您可能还想了解如何处理
unhandledRejection
错误。以下是最终解决方案:
nimxete23#
对于那些仍然有麻烦的人来说,这对我来说很有效:
await page.evaluate(()=>document.querySelector('#sign-in-btn').click())
基本上只是以不同的方式获取元素,然后单击它。
我不得不这样做的原因是因为我试图点击通知窗口中的一个按钮,该按钮位于应用程序的其他部分之外(Chrome似乎认为它是不可见的,即使它不是)。
lymgl2op4#
我知道我迟到了,但我发现了一个边缘案例,给了我很多悲伤,还有这个帖子,所以我想我会发布我的发现。
罪魁祸首:CSS
如果你有这个,你会有一个糟糕的时间。
解决方案:
希望这对你们中的一些人有帮助。
a6b3iqyw5#
我的方式
用途