爬虫的终极形态:nightmare

nightmare 是一个基于 electron 的自动化库(意思是说它自带浏览器),用于实现爬虫或自动化测试。相较于传统的爬虫框架(scrapy/pyspider),或者dom操作库(cheerio/jsdom),或者基于浏览器的自动化框架(selenium/phantomjs),他的优势在于提供了一个简洁有效 的编程模型。

来看官网给出的一个对比场景:

同样是实现一个向yahoo自动提交关键词并搜索的功能

1. PhantomJS实现

PhantomJS实现

 
 
 
 
 

JavaScript

 
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实现

 
 
 
 
 

JavaScript

 
1
2
3
4
yield Nightmare()
  .goto('http://yahoo.com')
  .type('input[title="Search"]', 'github nightmare')
  .click('.searchsubmit');

怎么玩

安装

 
 
 
 
 

Shell

 
1
yarn add nightmare

涉及到下载并编译一个electron,你国网速下需耐心等待

配置 options

 
 
 
 
 

JavaScript

 
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

实例化

 
 
 
 
 

JavaScript

 
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实现自动挂机呢?

大概分这么几步走:

  1. 先跳转到该网站
  2. 模拟输入帐号信息后点击submit
  3. 登录后等待主界面加载出现
  4. 在客户端起一个定时器,2秒一次轮询那个查岗按钮,发现就模拟点击
 
 
 
 
 

JavaScript

 
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,就是希望借助这种简洁模型的梳理,相对愉悦的实现自动化交互(至于标题,终归是意义过剩的产物,请忽略他的招摇。

爬虫的终极形态:nightmare的更多相关文章

  1. nodejs爬虫笔记(五)---利用nightmare模拟点击下一页

    目标 以腾讯滚动新闻为例,利用nightmare模拟点击下一页,爬取所有页面的信息.首先得感谢node社区godghdai的帮助,开始接触不太熟悉nightmare,感觉很高大上,自己写代码的时候问题 ...

  2. nodejs爬虫笔记(四)---利用nightmare解决加载更多问题

    目标: 解决页面加载更多问题.笔记三中,我们只爬取到网页的部分信息,而点击加载更多后的页面内容是没有提取到的.开始我的想法是找到加载更多的数据接口(可参照:http://www.jianshu.com ...

  3. etlpy: 并行爬虫和数据清洗工具(开源)

    etlpy是python编写的网页数据抓取和清洗工具,核心文件etl.py不超过500行,具备如下特点 爬虫和清洗逻辑基于xml定义,不需手工编写 基于python生成器,流式处理,对内存无要求 内置 ...

  4. Python数据挖掘(爬虫强化)

    (我喜欢雨天,因为雨天我可以回到童年踩水花!哈!) 2018年 --7月--12日 : 多云又暴雨 T—T 前言 我要把爬虫的终极利器介绍一下,这个只要是我们肉眼能看到的,就算在源码中或者在json中 ...

  5. Scrapy爬虫框架教程(四)-- 抓取AJAX异步加载网页

    欢迎关注博主主页,学习python视频资源,还有大量免费python经典文章 sklearn实战-乳腺癌细胞数据挖掘 https://study.163.com/course/introduction ...

  6. python爬取github数据

    爬虫流程 在上周写完用scrapy爬去知乎用户信息的爬虫之后,github上star个数一下就在公司小组内部排的上名次了,我还信誓旦旦的跟上级吹牛皮说如果再写一个,都不好意思和你再提star了,怕你们 ...

  7. 几个常用Json组件的性能测试

    上一篇文章中我已经介绍了JsonBuilder方案的整体思路以及一个版本的雏形代码,他现在已经是可以使用的了,但是因为是实时反射的,所以效率并不高. 鉴于几位博友对Json转换组件的性能有兴趣,我先放 ...

  8. Android消息处理机制(Handler 与Message)---01

    一.handler的使用场景为么会有handler?(部分内容图片摘自http://www.runoob.com/w3cnote/android-tutorial-handler-message.ht ...

  9. Kotlin封装RxJava与Retrofit

    代码地址:https://github.com/DarkPointK/RxTrofit.git 前言 Retrofit是Square公司开发的一个类型安全的Java和Android 的REST客户端库 ...

随机推荐

  1. redis服务后台运行

    文章目录 进入redis的安装目录 查看目录结构 进入src目录,普通启动效果 编辑redis服务目录下的redis.conf 进入src目录,执行后台运行的命令 检查服务是否开启 进入redis的安 ...

  2. HDFS under replicated blocks

    under replicated blocks 解决: 找出没有复制的block: hdfs fsck / | grep 'Under replicated' | awk -F':' '{print ...

  3. 深入理解Android-清晰的理解Service

    1.什么是Service 2.Service的生命周期 3.Service的工作过程 4.Service的start和bind状态有什么区别? 5.同一个Service,先startService,然 ...

  4. (转)小白科普, netty 有啥用?

      随着移动互联网的爆发性增长,小明公司的电子商务系统访问量越来越大,由于现有系统是个单体的巨型应用,已经无法满足海量的并发请求,拆分势在必行. 在微服务的大潮之中, 架构师小明把系统拆分成了多个服务 ...

  5. Spring 泛型依赖注入(3)

    BaseService<T>:有RoleService和UserService两的子类 BaseRepepositry<T>:有UserRepository和RoleRepos ...

  6. printk函数

    一个不同是 printk 允许你根据消息的严重程度对其分类, 通过附加不同的记录级别或者 优先级在消息上. 你常常用一个宏定义来指示记录级别. 例如, KERN_INFO, 我们之前曾 在一些打印语句 ...

  7. thinkphp3.2.3 nginx 连接mysql 报错 new PDO 异常

    在 php.ini 里重新指定mysql.sock 路径 pdo_mysql.default_socket=/Applications/XAMPP/xamppfiles/var/mysql/mysql ...

  8. string json list

    String str="[{\"cIndex\":14,\"column\":\"nextAdvice\",\"id\& ...

  9. bat删除多少天前的文件包含子目录

    通过 Forfiles 删除指定目录下过期的备份文件 /*-- 用法详解 D:/>forfiles /? FORFILES [/P pathname] [/M searchmask] [/S] ...

  10. 关于JAVA项目中CLASSPATH路径详解

    写的不错:http://blog.csdn.net/cheney521/article/details/8672066 以下内容源于复制,把自己觉得不错的东西收集起来: 在dos下编译java程序,就 ...