一、nightmare
Nightmare 是一个基于 Electron 的框架,利用了 Electron 提供的 Browser 的环境,用于 Web 自动化测试和爬虫(其实爬虫这个是大家自己给这个框架加的功能),可以在页面上模拟用户的行为触发一些异步数据加载。
具体的安装使用方法见官网http://www.nightmarejs.org/ 。
小贴士:
二进制的 Electron 依赖有点大,安装时间比较长,可以参照https://blog.tomyail.com/install-electron-slow-in-china/ ,加速electron在国内的下载速度。
这里贴一个nightmare在github上的示例:
var Nightmare = require('nightmare');
var nightmare = Nightmare({ show: true });
nightmare
.goto('https://duckduckgo.com')
.type('#search_form_input_homepage', 'github nightmare')
.click('#search_button_homepage')
.wait('#zero_click_wrapper .c-info__title a')
.evaluate(function () {
// 该环境中能使用浏览器中的任何对象window/document,并且返回一个promise
return document.querySelector('#zero_click_wrapper .c-info__title a').href;
})
.end()
.then(function (result) {
console.log(result);
})
.catch(function (error) {
console.error('Search failed:', error);
});
交互常用api
- goto(url[,headers]) url为你要跳转的网站url
- wait(selector) 等待某个dom元素出现
- type(selector[,text]) 在selector元素中输入text文本
- click(selector) 点击某个dom元素
- evaluate(fn[,agr1,agr2,…]) 在客户端注入JS脚本并执行 也就是你自己要封装数据的代码
- end() 执行完成,等待对数据的处理
由于在实际做爬虫项目时,发现框架自带的浏览器有兼容性导致页面无法正常加载,就没有采用这个框架,这里只做简单介绍,有兴趣的同学可以去官网详细了解。
二、nightwatch
什么是Nightwatch?
Nightwatch.js是一个使用Node.js编写的,用于Web应用程序和网站的自动化测试框架,和nightmare.js的不同之处在于它使用W3C WebDriver API来驱动浏览器,以便对DOM元素执行命令和断言。
在大多数情况下,Nightwatch至少需要向WebDriver服务器发送2个请求才能执行命令或声明,第一个请求是在给定CSS选择器(或Xpath表达式)的情况下定位元素的请求,下一个要执行的请求给定元素上的实际命令/声明。
Nightwatch有两种方式去调起浏览器跑测试
1、通过Selenium,调各个浏览器的webDriver唤起浏览器。这个需要安装java、Selenium、webDriver
2、直接通过各家浏览器的webDriver调起对应的浏览器
我选择了第二种,这里就需要去安装的chrome的webDriver,npm i -D chromedriver
具体的安装使用配置方法见官网https://nightwatchjs.org/ 。
在做爬虫项目中的核心代码:
module.exports = {
'step one': function(browser) {
browser
.url('https://www.facebook.com/')
.waitForElementVisible('#login_form')
.setValue('#email', 'account')
.setValue('#pass', 'password')
.click('#loginbutton')
.waitForElementVisible('#userNav')
},
'step two': function(browser) {
browser
.url('https://www.###.com/search/groups/?q=vaping&epa=SERP_TAB')
.waitForElementVisible('#BrowseResultsContainer', 5000, 'the page is loaded')
.timeoutsAsyncScript(600000, function(result) {
console.log(result);
})
.executeAsync(function(successResults, done) {
new Promise(function(resolve, reject) {
if (/* 异步操作成功 */) {
resolve();
}
}).then(function(){
//处理一些数据 data
});
done(data);//异步操作结束执行
}, [successResults], function(results) {
//results.value === data;
});
},
'step three': (browser) => {
browser.end();
}
};
用到的api:
- url([url], [callback]) 检索当前页面的URL或导航到新URL
- waitForElementVisible([using], selector, [timeout],[message]) 元素在指定的时间内可见
- setValue(selector, inputValue, [callback]) 在selector元素中输入inputValue
- click(selector, [callback]) 点击某个dom元素,支持回调
- timeoutsAsyncScript(ms, [callback]) 设置.executeAsync执行的异步脚本在中止之前运行的时间(以毫秒为单位)
- execute(script, args, [callback] ) 在页面中注入一段JavaScript,假定执行的脚本是同步的
- executeAsync( script, args, [callback] ) 在页面中注入一段JavaScript,假定执行的脚本是异步的
在做项目时文档没细看,拿到execute( )就开始编码,导致掉在坑里一直出不来,这里就重点说下execute( ) executeAsync( )这两个api的具体用法。
this.demoTest = function (browser) {
browser.execute(function(arg1, arg2,) {
//......
return data;
}, [arg1, arg2,], function(result) {
// result.value === data
});
}
this.demoTest = function (browser) {
browser.executeAsync(function(arg1, arg2, done) {
setTimeout(function() {
done(data);
}, 500);
}, [arg1, arg2], function(result) {
// result.value === data
});
}
execute(script, args, [callback] ) executeAsync( script, args, [callback] ) 这两个api 注入的JavaScript代码是运行在浏览器端的,而浏览器端和客户端的通信很有必要,比如我们可能需要使用在客户端声明的全局变量,以及把在浏览器端得到的数据传递给客户端。
args会以数组的形式把来自客户端的变量作为参数传递给script 函数体作为参数使用,并且该函数体返回的值将返回给客户端。
不同点在于,executeAsync( )执行的是异步脚本,script函数体将done回调作为参数接收,异步操作完成后需要调用该回调。传递给done回调的值将返回给客户端,具体使用方法见上面的示例代码。
切记,切记,如果注入的JavaScript脚本里包含异步操作,一定要使用executeAsync( ),而非execute( )。
后记
这里我只是简单介绍一下nightwatch,更加详细具体的使用还是需要参考[官方文档](https://nightwatchjs.org/](https://nightwatchjs.org/)。
怎么修改浏览器的默认行为(比如弹出的订阅通知弹窗)还尚待解决,欢迎了解的小伙伴伴留言哈。