我正在使用’puppeteer’为NodeJS测试一个特定的网站.它似乎在大多数情况下工作正常,但有些地方报道:
Error: Node is either not visible or not an 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: ',handle));
- await handle.click(); // Error: Node is either not visible or not an HTMLElement
- })();
我试图模仿真实用户点击网站的行为,这就是我使用.click()而不是.goto()的原因,因为a标签有onclick事件.
解决方法
首先,传递给
puppeteer.launch()
的defaultViewport对象没有键,只有值.
您需要将其更改为:
- '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();
Note: You might also want to look into 07008.
这是最终的解决方案:
- '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: ',handle ) );
- await handle.click();
- await page.waitForNavigation();
- await browser.close();
- })();