nightmare 是一个基于 electron 的自动化库(意思是说它自带浏览器),用于实现爬虫或自动化测试。相较于传统的爬虫框架(scrapy/pyspider),或者dom操作库(cheerio/jsdom),或者基于浏览器的自动化框架(selenium/phantomjs),他的优势在于提供了一个简洁有效 的编程模型。
来看官网给出的一个对比场景:
同样是实现一个向yahoo自动提交关键词并搜索的功能
1. PhantomJS实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open(‘http://yahoo.com‘, function (status) {
page.evaluate(function () {
var el =
document.querySelector(‘input[title="Search"]‘);
el.value = ‘github nightmare‘;
}, function (result) {
page.evaluate(function () {
var el = document.querySelector(‘.searchsubmit‘);
var event = document.createEvent(‘MouseEvent‘);
event.initEvent(‘click‘, true, false);
el.dispatchEvent(event);
}, function (result) {
ph.exit();
});
});
});
});
});
|
2. nightmare实现
1
2
3
4
|
yield Nightmare()
.goto(‘http://yahoo.com‘)
.type(‘input[title="Search"]‘, ‘github nightmare‘)
.click(‘.searchsubmit‘);
|
怎么玩
安装
1
|
yarn add nightmare
|
涉及到下载并编译一个electron,你国网速下需耐心等待
配置 options
1
2
3
4
5
6
7
|
openDevTools: {
mode: ‘bottom‘, // 开发者工具位置:right, bottom, undocked, detach
},
show: true, // 要不要显示浏览器
dock: true, // 要不要在Dock上显示图标
waitTimeout: 60000, // .wait() 方法超时时长,单位:ms
executionTimeout: 86400000, // .evaluate() 方法超时时长,单位:ms
|
实例化
1
2
|
import Nightmare from ‘nightmare‘
const nightmare = new Nightmare(options)
|
交互用的API
简单介绍几个:
.goto(url[, headers])
跳转到url.viewport(width, height)
浏览器窗口大小.wait(selector)
等待某个dom元素出现.click(selector)
点击某个dom元素.type(selector[, text])
在某个dom元素中输入.inject(type, file)
在页面上挂载 js/css 文件内容.evaluate(fn[, arg1, arg2,...])
在客户端注入JS脚本并执行,从而实现electron模型下的C/S互动及数据交换- ……
自动登录并轮询的例子
有那么一个网站(比如叫chagang.site),在我登录进去后,会不定时的查岗,需要点击一个按钮以证明没有离线,怎么用nightmare实现自动挂机呢?
大概分这么几步走:
- 先跳转到该网站
- 模拟输入帐号信息后点击submit
- 登录后等待主界面加载出现
- 在客户端起一个定时器,2秒一次轮询那个查岗按钮,发现就模拟点击
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
nightmare
.goto(‘http://chagang.site/‘)
.viewport(1024, 768)
.cookies.clearAll()
.type(‘#username‘, ‘用户名‘)
.type(‘#password‘, ‘密码‘)
.click(‘input[type=submit]‘)
.wait(‘#mainContent‘)
.evaluate(() => {
/* eslint-disable */
function handle() {
// 一个叫inspector的button
var inspector = document.querySelector(‘#inspector‘);
if (inspector && inspector.style.visibility === ‘visible‘) {
inspector.click();
}
}
setInterval(handle, 2000);
/* eslint-enable */
})
.evaluate(() => document.title)
.then(title => console.log(`${title} => 加载完成`))
.catch(err => console.error(err))
|
好像也没有多难
小结
本文只涉及到API中的一小部分,宝贝都在文档里。用 nightmare,就是希望借助这种简洁模型的梳理,相对愉悦的实现自动化交互(至于标题,终归是意义过剩的产物,请忽略他的招摇。