初探自动化测试(爬虫)框架nightmare&nightwatch

一、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', '[email protected]')
      .setValue('#pass', 'pyhwuf-8camMu-novcof')
      .click('#loginbutton')
      .waitForElementVisible('#userNav')
  },
  'step two': function(browser) {
    browser
      .url('https://www.facebook.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/)。
怎么修改浏览器的默认行为(比如弹出的订阅通知弹窗)还尚待解决,欢迎了解的小伙伴伴留言哈。

你可能感兴趣的:(初探自动化测试(爬虫)框架nightmare&nightwatch)