Web 自动化工具 Selenium、 PhantomJS、 Chrome HeadLess 对比分析

网页自动化工具,主要是可以通过写代码的方式,自动打开网站,输入,自动与页面交互,得到输出。

我们通常用的按键精灵,抢票软件,基本都是标准的网页面自动化工具。

通过客户端技术启动浏览器进行编程

目前,主流的网页面自动化工具有:

  1. Selenium
  2. PhantomJS
  3. Chrome HeadLess

他们都可以完成网页面上面的各种交互,今天简单介绍一下其中两项技术。

历史介绍

2004 年,ThoughtWorks 内部开发使用的一个工具,于2005年制成初始的 Selenium-RC 发布,至今十五年,已经发展成为一套完整的前端页面测试生态解决方案。

selenium

2011年,浏览器大战进入高潮时间,赢家除了有 Google Chrome 之外,还有一个更大的赢家,就是 NodeJS, 浏览器大战对NodeJs的成熟起了不少催化作用。

同年,基于NodeJs技术的 PhantomJS 诞生,不同与 Selenium ,由于内置了一个 WebKit, PhantomJS 最大的特点就是 runnable without a UI,就是不用打开一个浏览器,就可以进行模拟操作了,这点 Selenium 是无法做到的。

phantomjs

2017 年, Chrome 发布的版本 59, 支持以 HeadLess 模式启动。 通过使用WebSocket连接, 让外部与它进行通信进行控制,所以严格的来说,Chrome HeadLess 仅是 Chrome 的一种启动方式,但它提供了一整套命令操作,官方也发布了基于Nodejs 的 Puppeteer 工具包,非常容易使用,也可以使用第三方或自己研发的包进行控制。

chrome-headless

技术概览

总体上来说,技术差别如下:

对比项目 Selenium PhantomJS Chrome HeadLess
依赖环境 需要安装浏览器和对应的driver 仅NodeJs 需要安装Chrome 或 Chrome-canary 或 Chromium,大部分框架基于Nodejs
编程环境 支持多种编程语言,主流的都在其中 JavaScript/TypeScript 简单的需求命令行,其它的扩展,目前基本都是JavaScript/TypeScript
主流框架 自带,少量三方 自带的 自带,三方相对较多
性能分析 有,功能同Chromen性能分析工具
浏览器 全部浏览器 WebKit内核 自带Chorme

相同点:

  1. 这三种技术,都可以直接或间接实现基础的网页面的各种页面操作,窗口管理,状态管理等基本功能,其中 PhantomJS 和 Chrome HeadLess 功能比较相似(Chrome HeadLess 设计之初参考对象就是前两者)
  2. 支持 Windows、 Linux、 macOS 操作系统,Linux 方面,由于发行版众多,三者貌似者仅在 Unbuntu 上做了测试,理论上其它发行版也没差。

不同点:

  1. PhantomJS 与 Chrome HeadLess ,最主要的不同是 PhantomJS 是内置的一个版本较低的 webkit 内核 ,而 Chrome HeadLess 的内核总是最新的,自家的 Blink 内核.
  2. Selenium 与后两者的不同一: 前者是基于机器上安装的浏览器,通过对应的 Driver 进行操作,后两都都是内置,不需要Driver中间层,所以前者可以支持几乎所有浏览器,后者只支持自己本身。
  3. Selenium 与后两者的不同二: 前者是更像是一整套生态解决方案,后两者仅像一个工具。前者支持各种主流开发语言,并且提供了 IDE 录屏回放工具,非常方便。后者则可通过第三工具库进行扩展。
  4. Selenium 与后两者的不同三: 后两者支持一些个性化的功能,比如保存PDF,浏览器功能开关等。

Selenium

Selenium 最大的特点就是系统非常完善,经过十多年的演化,Selenium已经构造出了自己的生态圈,由以下部分组成,可以根据不同情况选择使用。

  1. Selenium WebDriver : 包括了各种语言的库文件,远程控制器,
  2. Selenium IDE : 浏览器插件,支持 Chrome 与 FireFox
  3. Selenium Grid : 如果需要把任务放在一个集群上面,分布式运行,Selenium Grid是一个现成的解决方案。

不仅有强大的生态圈,Selenium 几乎支持所以浏览器(需要安装Driver),是其它技术无法比的,

  1. Chrome
  2. Firefox
  3. Safari
  4. Opera
  5. IE (仅IE11,且需要做一些额外配置)
  6. Edge

另外,Selenium 支持各种主流编程语言,包括

  1. Ruby
  2. Java
  3. Python
  4. C#
  5. JavaScript

所以,可以很轻松的将 Selenium 技术融入到目前正在使用的技术栈。

Selenium Grid: 如果需要把任务放在一个集群上面,分布式运行,Selenium Grid是一个现成的解决方案,

Chrome HeadLess

这里仅介绍后来者 Chrome HeadLess , 先行者 PhantomJS 由于功能和 Chrome HeadLess 大部分时候,不再推荐PhantomJS。

phantomjs-is-dead-use-chrome-headless-in-continuous-integration

使用 Chrome HeadLess 的两种方式

  1. 直接通过命令行,非常简单的业务,比如截图,打印等,直接运行命令就可
chrome \
  --headless \                   # 使用 headless 模式.
  --disable-gpu \                # Temporarily needed if running on Windows.
  --remote-debugging-port=9222 \  # 远程调试端口,默认9222
  https://www.xdnote.com   # 打开链接. 默认是 about:blank.

常用命令:

--dump-dom 打出页面DOM结构 
--print-to-pdf 导出PDF
--screenshot 屏幕截图
--window-size 设置网页大小
  1. 使用工具

    目前搭配 Chrome Headless 的官方工具,是 Puppeteer ,一句话:Google 团队出品。

const puppeteer = require('puppeteer');

(async() => {
const browser = await puppeteer.launch();
const page = await browser.newPage();

console.log(await browser.version());                                    // 打印 user agent
await page.goto('https://www.xdnote.com', {waitUntil: 'networkidle2'}); // 打开页面
await page.pdf({path: 'page.pdf', format: 'A4'});                        // 页面打印成PDF

await browser.close();                                                    // 关闭浏览器
})();

另外还有一个低层工具: chrome-remote-interface ,相对于Puppeteer, API更加底层,意味着更多的细节控制,也意味着实现起来需要更多的代码。

const CDP = require('chrome-remote-interface');

(async function() {

const chrome = await launchChrome();
const protocol = await CDP({port: chrome.port});

const {Page} = protocol;
await Page.enable();

Page.navigate({url: 'https://www.xdnote.com/'});    // 打开页面

// 等待 "window.onLoad"
Page.loadEventFired(async () => {
  const manifest = await Page.getAppManifest(); // 获取app mainfest

  if (manifest.url) {
    console.log('Manifest: ' + manifest.url);
    console.log(manifest.data);
  } else {
    console.log('Site has no app manifest');
  }

  protocol.close();
  chrome.kill(); // 关闭浏览器
});

})();

需要说明的是, chrome-remote-interface 并不会默认启动Chrome,所以你可以手动用命令行启动,或者使用 chrome-launcher 启动,比如:

const chromeLauncher = require('chrome-launcher');

function launchChrome(headless=true) {
  return chromeLauncher.launch({
    // port: 9222, // 默认9222
    chromeFlags: [
      '--window-size=412,732',
      '--disable-gpu',
      headless ? '--headless' : ''
    ]
  });
}

launchChrome().then(chrome => {
  console.log(`Chrome debuggable on port: ${chrome.port}`);
});

参考阅读

技术选型推荐

通常技术选型和需求相关,通常我们使用网页自动化框架,需求可能是以下几个之一:

  1. 编写测试用例:测试网页是否正常,录㓡行为等。
  2. 编写爬虫软件:传统的网络抓包爬虫无法拿到渲染后的页面
  3. 制作各类工具:流程处理、按键点击,外挂等等

粗暴推荐:

  1. Selenium 是一个万用的框架,基本可以作为首选,缺点是稍微比其他两个重一点,不是所有人都喜欢,总之,满足以下几点之一,选择 Selenium
  • 需要运行测试用例:Selenium最初就是用来做测试用例的,能与各种编程语言的单元测试框架完美结合
  • 需要跨浏览器测试:其他两个都无法支持全浏览器,Selenium甚至都可以支持IE。
  • 项目本身重量级别:重量级别项目,Selenium提供了一整套生态,大部分的实际问题都会有解决方案。
  • 不想使用NodeJs,想使用Python 或者 Java 等语言
  1. 不想用 Selenium 时,选择 Chrome HeadLess 即可, PhantomJS基本上没有绝对优势优于Chrome,总之,以下几点时,选择 Chrome Headless
  • 小型工具等开发:项目本身比较小,电脑上只需要安装Chrome浏览器即可,简单的需求甚至可以通过命令行完成而不需要编程。
  • 需要进行浏览器底层控制: Selenium 无法控制浏览器的一些底层行为,而Chome可以
  • 网页性能分析:和开发者工具一样,提供性能分析模块自由实用
  1. 实在不想安装 Chrome ,选择 PhantomJS 即可。