前言:
对于富客户端的 Web 应用页面,自动登录、页面修改、抓取页面内容、屏幕截图、页面功能测试…面对这些需求,使用后端语言需要花费不少的精力才能实现, 通常这是因为这些网站会判断访问站点的客户端是否是一个真实的浏览器,此时 SlimerJS、phantomJS 或 CasperJS 或许是更好的一种选择。
使用PhantomJS(webkit)或者SlimerJS (Gecko) 配合 CasperJS获取JavaScript渲染后的网页内容以及内嵌子(iFrame 里的内容)网页渲染后的内容, 那么这样做到底能为我们做什么?坏笑,我就不多说了,当然是来帮我分析解决网页的问题了,然后是网络爬虫,还能做什么不好的事?相信大家是可意会不可言传,不就是这么不言而喻吗!!
要实现这些功能,除了 使用PhantomJS(webkit)或者SlimerJS (Gecko) 配合 CasperJS以外,当然还有其他途径了。如下(至于孰优孰劣在下不做任何评论,各位看官自己研究研究吧):
基于chromiun的swing组件
http://www.teamdev.com/jxbrowser
Swing使用JavaFX的方式
http://www.tuicool.com/articles/N7J3au
http://docs.oracle.com/javafx/2/webview/jfxpub-webview.htm
DJ NativeSwing
非常强大,可以使用IE、 Firefox, XULRunner or Webkit
http://gongqi.iteye.com/blog/754231
http://sourceforge.net/projects/djproject/
XULRunner方式
http://wiki.netbeans.org/EmbeddedBrowser
基于MozSwing(独立运行,不依赖客户机器的浏览器版本)
看参看博文:http://blog.csdn.net/lxf9601/article/details/6967167
该博文的源码:http://download.csdn.net/detail/lxf9601/3808104
该博文源码的相关说明:http://blog.csdn.net/lxf9601/article/details/6985848
pyquery
Python的一个jQuery库,http://pythonhosted.org//pyquery/api.html
介绍:
1、PhantomJS
源码:https://github.com/ariya/phantomjs
官网:http://phantomjs.org/ (说明文档和api都可以从官网上找到)
当前最新版本 2.1.1.
PhantomJS是一个基于WebKit的服务器端JavaScript API,它基于 BSD开源协议发布。PhantomJS无需浏览器的支持即可实现对Web的支持,且原生支持各种Web标准,如DOM 处理、JavaScript、CSS选择器、JSON、Canvas和可缩放矢量图形SVG。PhantomJS主要是通过JavaScript和CoffeeScript控制WebKit的CSS选择器、可缩放矢量图形SVG和HTTP网络等各个模块.
PhantomJS应用于:
- 1.无需浏览器的Web测试:支持很多测试框架,如YUI Test、Jasmine、WebDriver、Capybara、QUnit、Mocha
- 2.页面自动化操作:使用标准的DOM API或一些JavaScript框架(如jQuery)访问和操作Web页面。
- 3.屏幕捕获:以编程方式抓起CSS、SVG和Canvas等页面内容,即可实现网络爬虫应用。构建服务端Web图形应用,如截图服务、矢量光栅图应用。
- 4.网络监控:自动进行网络性能监控、跟踪页面加载情况以及将相关监控的信息以标准的HAR格式导出。
基于PhantomJS的扩展包:
- CasperJS:一个开源的导航脚本处理和高级测试工具
- Poltergeist :测试工具Capybara的测试驱动
- Guard::Jasmine:能够基于Rails实现自动化测试Jasmine的Specs
- GhostDriver:远程 WebDriver 有线协议的开源实现
- PhantomRobot:PhantomJS机器人测试框架
- Mocha-PhantomJS:JavaScript测试框架Mocha的客户端
- capturejs、pageres、phantomjs-screenshots、manet、screenshot-app : 截屏工具
使用方式:
- 1.官网下载phantomjs,包括 Windows ,Mac OS,Linux版本,自行选择对应 版本下载解压即可,其中带有一个example文件夹,里面有很多已经写好的代码供使用。
- 2.配置环境变量:在环境变量path中添加phantomjs的bin路径
- 3.编写自己脚本,使命令:phantomjs 脚本路径 运行。
例子:
console.log('Hello, world!');
phantom.exit();
保存为hello.js, 执行:phantomjs hello.js 输出结果为:Hello, world!
2、SlimerJS
源码:https://github.com/laurentj/slimerjs官网:https://slimerjs.org帮助文档:http://docs.slimerjs.org/current/使用 slimerjs 抓取 DDos 保护的站点: http://www.tuicool.com/articles/myqAF3
SlimerJS 是一个提供给 Web 开发人员,一个基于WebKit的服务器端JavaScript API,可通过脚本编程控制的浏览器。它可以让你使用 Javascript 脚本操纵一个网页:打开一个网页,点击链接,修改的内容等,这对于做功能测试,页面自动机,网络监控,屏幕捕获等是非常有用的。事实上,它是类似 PhantomJS 的一个工具,但是 SlimerJS 只能运行在 Gecko (Firefox)上而不是Webkit。SlimerJS 提供几乎和 PhantomJS 相同的 API,高度兼容 PhantomJS。SlimerJS 不仅是 PhantomJS 的一个克隆,还包含额外的功能。其语法与PhantomJS几乎没有任何差别,高度兼容兼容 CasperJS。
与PhantomJS 的区别
- PhantomJS 基于 Webkit 内核,不支持 Flash 的播放
- SlimerJS 基于火狐的 Gecko 内核,支持 Flash播放,并且执行过程会有页面展示
功能(几乎可以使用 javascript 模拟在浏览器上的任何操作)
- 1.打开页面
- 2.前进/后退
- 3.页面点击
- 4.鼠标滚动
- 5.DOM 处理
- 6.CSS 选择器
- 7.Canvas 画布
- 8.SVG画图
使用方式(和PhantomJS 的使用法方式没有区别):
- 1.官网下载SlimerJS ,解压
- 2.配置环境变量:在环境变量path中添加SlimerJS 的bin路径
- 3.编写自己脚本,使命令:slimerjs 脚本路径 运行。
实现页面的某个区域截图,SlimerJS 与PhantomJS 的示例 SlimerJS 示例
var webpage = require('webpage').create();webpage.open('http://www.meizu.com') // 打开一个网页.then(function() { // 页面加载完成后执行 //保存页面截屏 webpage.viewportSize = { width: 650, height: 320 }; webpage.render('page.png', { onlyViewport: true }); //再打开一个网页 return webpage.open('http://bbs.meizu.com');}).then(function() { // 点击某个位置 webpage.sendEvent("click", 5, 5, 'left', 0); slimer.exit(); //退出});
PhantomJS 示例
var webpage = require('webpage').create();
webpage.open('http://www.meizu.com', function (status) {
//打开一个页面
}).then(function(){
//保存页面截屏
webpage.viewportSize = {
width: 650,
height: 320
};
webpage.render('page.png', {
onlyViewport: true
});
//再打开一个网页
return webpage.open('http://bbs.meizu.com');
}).then(function(){
webpage.sendEvent("click", 5, 5, 'left', 0);
phantom.exit();
});
3、CasperJS
源码:https://github.com/casperjs/casperjs官网:http://casperjs.org/帮助文档:http://docs.casperjs.org/en/latest/
当前版本 1.1.3。
CasperJS 是一个开源的导航脚本和测试工具,使用 JavaScript 基于 PhantomJS 编写,用于测试 Web 应用功能,Phantom JS是一个服务器端的 JavaScript API 的 WebKit。其支持各种Web标准: DOM 处理, CSS 选择器, JSON, Canvas, 和 SVG。
CasperJS 按照start()、then*()、wait*()、open()等流程往下做导航(注意,如果有语法错误,比如少个分号神马的,可能运行时就无任何提示的卡那里了)run()方法触发该流程,run()方法可以指定一个onComplete()方法供导航完成时回调 exit()/die()退出 this.getPageContent() 可以查看渲染后的页面内容
它提供了一套用于 Web 应用测试的方法组件,这些组件基于 PhantomJS 或 SlimerJS 所提供的 javascript API,实现对 Web 应用的功能执行。CasperJS 简化了完整的导航场景的过程定义,提供了用于完成常见任务的实用的高级函数、方法和语法。如:
- 定义和整理导航步骤
- 表单填充
- 点击、跟踪链接
- 区域、页面截图
- 断言远程DOM
- 日志、事件
- 资源下载,包括二进制资源
- 捕捉错误,并做出相应的响应
- ……
使用方式:
- 1.依赖PhantomJS, 所以需要先安装好PhantomJS,并且配置好PhantomJS的环境变量。
- 2.官网下载CasperJS ,解压到指定位置,配置环境变量, 同PhantomJS的环境变量配置方式一样
- 3.命令:casperjs -version 查看是否安装成功
- 4.运行:casperjs 脚本
CasperJS 前端自动化测试脚本 示例:
var utils = require('utils');
var webpage = require('casper').create({
//verbose: true,
logLevel: 'debug',
viewportSize: {
width: 1024,
height: 768
},
pageSettings: {
loadImages: true,
loadPlugins: true,
XSSAuditingEnabled: true
}
});
//打开页面
webpage.start()
.thenOpen('http://www.meizu.com', function openMeizu(res) {
this.echo('打印页面信息');
res.body = '';//不打印body信息
utils.dump(res);
//点击登录按钮
if (this.exists("#_unlogin")) {
this.echo('点击登录按钮');
this.click("#_unlogin a:nth-child(1)");
this.wait(3000, function wait3s_1() {
if (this.exists("form#mainForm")) {
this.echo("需要登陆,填充账号信息。。。");
//填充表单账号
this.fill('form#mainForm', {
'account': 'lzwy0820@flyme.cn',
'password': '********'
}, true);
this.capture('meizu_login_page.png');
this.wait(3000, function wait3s_2() {
//登录按钮存在,点击
if (this.exists("#login")) {
this.echo('提交登录');
this.click("#login");
}
});
}
});
}
})
.then(function capture() {
if (this.exists('#mzCustName')) {
this.echo('登录成功!开始截图存储..');
} else {
this.echo('登录失败!请查看截图文件')
}
//截图
this.capture('meizu.png');
this.captureSelector('meizu_header.png', 'div.meizu-header');
})
.then(function exit() {
this.echo('执行完成,退出');
this.exit();
})
.run();
CasperJS 抓取 Javascript 渲染的网页 示例: 下面的代码,会抓取网易云音乐的页面,运行Javascript,然后把最终的HTML保存在文本里。
// http://casperjs.org/var casper = require('casper').create({ pageSettings: { loadImages: false, // 不加载图片,减少请求 }});var fs = require('fs');casper.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36');casper.start();casper.viewport(1024, 768);casper.then(function() { this.open('http://music.163.com/#/m/discover/artist/').then(function(){ this.page.switchToChildFrame(0); // 页面包含 iFrame fs.write("1.html", this.getPageContent(), 'w'); // 保存 iFrame 里的内容 this.page.switchToParentFrame(); fs.write("2.html", this.getPageContent(), 'w'); });});casper.run();
CasperJS 循环调用示例: 解决方案是递归调用,casperjsObj调用run函数时可以传入一个结束时执行的函数,在这个函数里面可以加入【我们的循环体】和【递归的run调用】
function refresh(){
this.wait(10000,
function() {
this.click('a[title="简历刷新"]');
this.log('refreshed my resume');
}
);
this.run(refresh);
}
casper.run(refresh);
日志中出现”Unsafe JavaScript attempt to access frame with URL”的info信息,启动casperjs时候加上参数–web-security=false(allow cross-domain XHR)即可(参见http://stackoverflow.com/questions/18960791/cant-run-a-basic-test-with-casperjs)
要治本的话,参见http://stackoverflow.com/questions/4324108/unsafe-javascript-attempt-to-access-frame-with-url