可编程浏览器 – PhantomJS

可编程浏览器,目前主要有两个
1 PhantomJs,打包Webkit,主要提供JS编程接口
2 SlimerJs,需要独立安装Firefox,依赖这个独立安装的Firefox内核,提供JS编程接口

这两个工具提供的JS编程接口较原始,可以使用CasperJS(http://casperjs.org/)来操作(Node.js模块)。

>>>开始
1 下载
http://phantomjs.org/download.html,直接下载二进制包。
2 构建(Build)
建议直接使用二进制包。
3 最新发布
http://phantomjs.org/releases.html
4 Release Names
5 REPL
PhantomJS 1.5起,提供一个交互模式(在命令行里面直接输入代码运行)

phantomjs.exe	//进入交互模式
phantomjs> phantom.version
{
   "major": 2,
   "minor": 1,
   "patch": 1
}
phantomjs> console.log("phantomjs");
phantomjs
undefined

phantomjs> window.navigator
{
   "appCodeName": "Mozilla",
   "appName": "Netscape",
   "appVersion": "5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1",
   "cookieEnabled": true,
   "language": "zh-CN",
   "mimeTypes": {
      "length": 0
   },
   "onLine": true,
   "platform": "Win32",
   "plugins": {
      "length": 0
   },
   "product": "Gecko",
   "productSub": "20030107",
   "userAgent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1",
   "vendor": "Apple Computer, Inc.",
   "vendorSub": ""
}

CTRL+C或CTRL+D或输入phantom.exit()退出交互模式。支持自动完成和历史记录。

>>>学习
1 开速开始

console.log('Hello, world!');
phantom.exit();

//截屏
var page = require('webpage').create();
page.open('http://example.com', function(status) {
	console.log("Status:" + status);
	if(status === "success") {
		page.render('example.png');
	}
	phantom.exit();
});

//测试加载时间
//phantomjs.ext loadspeed.js http://blog.ifeeline.com
var page = require('webpage').create(),
  system = require('system'),
  t, address;

if (system.args.length === 1) {
  console.log('Usage: loadspeed.js <some URL>');
  phantom.exit();
}

t = Date.now();
address = system.args[1];
page.open(address, function(status) {
  if (status !== 'success') {
    console.log('FAIL to load the address');
  } else {
    t = Date.now() - t;
    console.log('Loading ' + system.args[1]);
    console.log('Loading time ' + t + ' msec');
  }
  phantom.exit();
});

// evaluate()方法,只能返回简单对象,不能包含函数
// 并且evaluate()不能访问page只能的内容
var page = require('webpage').create();
page.open(url, function(status) {
  var title = page.evaluate(function() {
    return document.title;
  });
  console.log('Page title is ' + title);
  phantom.exit();
});

// 在evaluate()方法内部的console信息是不能显示的
// 不过可以在page的onConsoleMessage来实现
// 同时也是一个提取信息的有用办法
var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
  console.log('Page title is ' + msg);
};
page.open(url, function(status) {
  page.evaluate(function() {
    console.log(document.title);
  });
  phantom.exit();
});

//以下实例展示了跟踪请求 和 响应
var page = require('webpage').create();
page.onResourceRequested = function(request) {
  console.log('Request ' + JSON.stringify(request, undefined, 4));
};
page.onResourceReceived = function(response) {
  console.log('Receive ' + JSON.stringify(response, undefined, 4));
};
page.open(url);

2 自动化测试
3 截屏

// 支持png jpg  gif  pdf
var page = require('webpage').create();
page.open('http://github.com/', function() {
  page.render('github.pdf');
  phantom.exit();
});

4 网络监控
5 页面自动化

// 设置用户代理
var page = require('webpage').create();
console.log('The default user agent is ' + page.settings.userAgent);
page.settings.userAgent = 'SpecialAgent';
page.open('http://www.httpuseragent.org', function(status) {
  if (status !== 'success') {
    console.log('Unable to access network');
  } else {
    var ua = page.evaluate(function() {
      return document.getElementById('myagent').textContent;
    });
    console.log(ua);
  }
  phantom.exit();
});
输出:
The default user agent is Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1
Your Http User Agent string is: SpecialAgent

// 使用jQuery来操作页面
// 在page.includeJs中必须使用 phantom.exit()来退出
var page = require('webpage').create();
page.open('http://www.sample.com', function() {
  page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
    page.evaluate(function() {
      $("button").click();
    });
    phantom.exit()
  });
});

// 页面的内容
page.content
page.plainText
// 页面的cookies(包括页面在渲染是JS产生的cookie)
page.cookies
// 页面设置,当前只有一个值userAgent
page.settings.userAgent = ‘SpecialAgent’;
// 页面URL
page.url
// 页面视口大小(浏览器尺寸)
page.viewportSize
{
	width:1024,
	height:768
}
////////////////////////////////////
// 函数列表

    page.childFramesCount
    page.childFramesName
    page.close
    page.currentFrameName
    page.deleteLater
    page.destroyed
    page.evaluate
    page.initialized
    page.injectJs
    page.javaScriptAlertSent
    page.javaScriptConsoleMessageSent
    page.loadFinished
    page.loadStarted
    page.openUrl
    page.release
    page.render
    page.resourceError
    page.resourceReceived
    page.resourceRequested
    page.uploadFile
    page.sendEvent
    page.setContent
    page.switchToChildFrame
    page.switchToMainFrame
    page.switchToParentFrame
    page.addCookie
    page.deleteCookie
    page.clearCookies

// 回调列表

    onInitialized
    onLoadStarted
    onLoadFinished
    onUrlChanged
    onNavigationRequested
    onRepaintRequested
    onResourceRequested
    onResourceReceived
    onResourceError
    onResourceTimeout
    onAlert
    onConsoleMessage
    onClosing

6 进程间通信
写入到文件
对外HTTP请求(GET或POST数据,在页面中通过XMLHttpRequest),跨域是禁止的
来自外部的HTTP请求(提供WebServer模块)
路由PhantomJS的流量通过一个代理(比如fiddler)
7 命令行工具
phantomjs [options] somescript.js [arg1 [arg2 […]]]

// 最为有用的是指定cookies保存的路径
–cookies-file=/path/to/cookies.txt specifies the file name to store the persistent Cookies.
–local-to-remote-url-access=[true|false] allows local content to access remote URL (default is false). Also accepted: [yes|no].

Phantomjs 1.3后,可以通过–config=/config.json来指定配置:

config.json
{
	"cookiesFile": "cookies.text"
}

phantomjs.exe --cookies-file=cookies.txt cookie.js
phantomjs.exe --config=config.json cookie.js

>>> 探索
1 实例
2 最佳实践
推荐使用自动化测试框架,高层封装CasperJS
3 提示和技巧
4 Supported Web Standards
5 Buzz
6 Who’s using PhantomJS?
7 Related Projects
http://phantomjs.org/related-projects.html