我正在使用'puppeteer'为NodeJS测试一个特定的网站.它似乎在大多数情况下工作正常,但有些地方报道:
错误:节点不可见或不是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
})();
Run Code Online (Sandbox Code Playgroud)
我试图模仿真实用户点击网站的行为,这就是我使用的原因.click()
,而不是.goto()
因为a
标签有onclick
事件.
Bor*_*ris 13
如果你有类似的东西
const button = await page.$(selector);
await button.click();
Run Code Online (Sandbox Code Playgroud)
尝试改变
await button.click();
Run Code Online (Sandbox Code Playgroud)
到
await button.evaluate(b => b.click());
Run Code Online (Sandbox Code Playgroud)
不同的是,button.click()
使用木偶的点击ElementHandle.click()
这
而button.evaluate(b => b.click())
通过在浏览器中HTMLElement.click()
的给定元素上运行 JavaScript方法来“点击”元素,这会触发一个事件。它不会滚动页面或移动鼠标,即使元素在屏幕外也能工作。click
chr*_*ine 10
对于仍然遇到麻烦的人,这对我有用:
await page.evaluate(()=>document.querySelector('#sign-in-btn').click())
基本上只是以不同的方式获取元素,然后单击它。
我必须这样做的原因是因为我试图单击位于应用程序其余部分之外的通知窗口中的按钮(Chrome 似乎认为它是不可见的,即使它不是)。
首先defaultViewport
,您传递给的对象puppeteer.launch()
没有键,只有值.
您需要将其更改为:
'defaultViewport' : { 'width' : width, 'height' : height }
Run Code Online (Sandbox Code Playgroud)
您传递给的对象也是如此page.setViewport()
.
您需要将此行代码更改为:
await page.setViewport( { 'width' : width, 'height' : height } );
Run Code Online (Sandbox Code Playgroud)
三,函数page.setUserAgent()
返回a promise
,所以你需要await
这个函数:
await page.setUserAgent( 'UA-TEST' );
Run Code Online (Sandbox Code Playgroud)
此外,你忘了添加分号后handle = handles[12]
.
你应该改为:
handle = handles[12];
Run Code Online (Sandbox Code Playgroud)
此外,page.waitForNavigation()
单击第一个链接后,您不会等待导航完成().
点击第一个链接后,您应该添加:
await page.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)
我注意到第二页有时会挂起导航,因此您可能会发现增加默认导航超时(page.setDefaultNavigationTimeout()
)非常有用:
page.setDefaultNavigationTimeout( 90000 );
Run Code Online (Sandbox Code Playgroud)
再一次,你忘了添加分号后handle = handles[12]
,所以需要将其更改为:
handle = handles[12];
Run Code Online (Sandbox Code Playgroud)
请务必注意,您正在使用错误的选择器来处理您单击的第二个链接.
您的原始选择器试图选择仅对xs
超小屏幕(手机)可见的元素.
您需要收集一组对您指定的视口可见的链接.
因此,您需要将第二个选择器更改为:
div[id$="-KcazEUq"] article .dfo-widget-sm a
Run Code Online (Sandbox Code Playgroud)
您还应该在点击第二个链接后等待导航完成:
await page.waitForNavigation();
Run Code Online (Sandbox Code Playgroud)
最后,您可能还想browser.close()
在完成程序后关闭浏览器():
await browser.close();
Run Code Online (Sandbox Code Playgroud)
注意:您可能还想查看处理
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();
})();
Run Code Online (Sandbox Code Playgroud)
小智 5
我知道我参加聚会迟到了,但我发现了一个让我非常悲伤的边缘案例,还有这个帖子,所以我想我会发布我的发现。
罪魁祸首:CSS
scroll-behavior: smooth
Run Code Online (Sandbox Code Playgroud)
如果你有这个,你会过得很糟糕。
解决方案:
await page.addStyleTag({ content: "{scroll-behavior: auto !important;}" });
Run Code Online (Sandbox Code Playgroud)
希望这对你们中的一些人有所帮助。
归档时间: |
|
查看次数: |
3790 次 |
最近记录: |