Web 自动化测试与智能爬虫利器:PhantomJS 简介与实战

估计部分同学没听过这个工具,那先简单介绍下它的背景与作用。

1、PhantomJS 是什么?

PhantomJS是一个基于WebKit的服务器端JavaScript API,它无需浏览器的支持即可实现对Web的支持,且原生支持各种Web标准,如DOM 处理、JavaScript、CSS选择器、JSON、Canvas和可缩放矢量图形SVG。PhantomJS主要是通过JavaScript和CoffeeScript控制WebKit的CSS选择器、可缩放矢量图形SVG和HTTP网络等各个模块。PhantomJS主要支持Windows、Mac OS、Linux三个平台,并且提供了对应的二进制安装包。

PhantomJS 的使用场景如下:

  • 无需浏览器的Web测试:无需浏览器的情况下进行快速的Web测试,且支持很多测试框架,如YUI Test、Jasmine、WebDriver、Capybara、QUnit、Mocha等。
  • 页面自动化操作:使用标准的DOM API或一些JavaScript框架(如jQuery)访问和操作Web页面。
  • 屏幕捕获:以编程方式抓起CSS、SVG和Canvas等页面内容,即可实现网络爬虫应用。构建服务端Web图形应用,如截图服务、矢量光栅图应用。
  • 网络监控:自动进行网络性能监控、跟踪页面加载情况以及将相关监控的信息以标准的HAR格式导出。

PhantomJS 已形成了一个功能非常强大的生态圈内容,相关项目如下:

  • CasperJS:一个开源的导航脚本处理和高级测试工具
  • Poltergeist :测试工具Capybara的测试驱动
  • Guard::Jasmine:能够基于Rails实现自动化测试Jasmine的Specs
  • GhostDriver:远程 WebDriver 有线协议的开源实现
  • PhantomRobot:PhantomJS机器人测试框架
  • Mocha-PhantomJS:JavaScript测试框架Mocha的客户端

此外,生态圈还包括基于PhantomJS实现了众多截屏工具,如capturejs、pageres、phantomjs-screenshots、manet、screenshot-app等;以及Node.js、Django、PHP、Sinatra等语言的截图API和Confess、GhostStory、Grover等众多工具。

PhantomJS当前最新版本是2.0,目前除了 Linux 的二进制版本未发布之外,其它跨平台的版本都发布了二进制与源码包可供选择,本文所用的测试环境来源于 Windows 二进制 2.0 版本。

2、PhantomJS VS Selenium

去年在《WEB 自动化测试工具 Selenium 简介及其应用》一文中介绍过 Selenium 的用法与功能,其实它也是一个 Web 自动化测试工具,是 ThoughtWorks专门为Web应用程序编写的一个验收测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7、8、9)、Mozilla Firefox、Mozilla Suite等。这个工具的主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和操作系统之上。测试系统功能——创建衰退测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。

用过的同学估计都有感受,就是这货本质上是依赖于浏览器的,每一步操作都是直接操纵图形化的浏览器,这样无论是从性能还是可编程性上来说都差多了,而今天介绍的 PhantomJS 则不然,它除了拥有 Selenium 的绝大部分功能之外,更强大的地方在于他是一个“无头浏览器”,没有图形化界面,直接面向程序 API 接口,性能和可操作性比 Selenium 高了很多。这两个工具最重要的就是能执行页面 JS,现在流行的基本如下几种:

  • QtWebKit,已知有 Python 和 C++ 支持
  • PhantomJS,已知有 JavaScript、CoffeeScript 和 Python 支持,也是 Webkit 内核
  • SlimerJS,已知有 JavaScript 支持,Gecko 内核,和火狐是一样的,也可以运行于火狐之上
  • CasperJS,已知有 JavaScript 支持。上边两个的进一步封装

这个重要的特性使得他们和一些爬虫框架组合起来使用之后,目测一大波智能爬虫正向我们走来~    -_-|||

3、实战:抓取某个页面所有的子请求

简单的入门教程这里就不说了,可以参考官方文档或者文末链接,假设我们现在有个需求,需要抓取、分析某个页面加载时浏览器发起的所有的子请求,效果如下如所示:

其实,这个功能 phantomjs examples 的 netlog.js 已经实现了,但是官方的例子在网络不好、页面复杂的时候容易漏掉请求,我这里稍作了修改:

var page = require(‘webpage‘).create(),
system = require(‘system‘),
address;

if (system.args.length === 1) {
    console.log(‘Usage: netlog.js <some URL>‘);
    phantom.exit(1);
} else {
    address = system.args[1];

    page.onResourceRequested = function (req) {
        //console.log(‘requested: ‘ + JSON.stringify(req, undefined, 4));
        console.log(JSON.parse(JSON.stringify(req, undefined, 4)).url);
    };

    //page.onResourceReceived = function (res) {
    //    console.log(‘received: ‘ + JSON.stringify(res, undefined, 4));
    //};

    page.open(address, function (status) {
        if (status !== ‘success‘) {
            console.log(‘FAIL to load the address‘);
        }
        window.setTimeout(function () {
            phantom.exit(1);
        }, 5000);
    });
}

效果:

timeout 30 phantomjs netlog.js http://bj.fang.ooxx.com
http://bj.fang.ooxx.com/
http://include.aifcdn.com/aifang/res/2015042706/b/Aifang_Web_Loupan_List_ListIndex.css
http://pages.aifcdn.com/prism/performance.js?v=1416480080
http://pages.aifcdn.com/js/jquery-1.9.1/jquery-1.9.1.min.js
http://pages.aifcdn.com/js/aa/bb.js
http://include.aifcdn.com/aifang/res/2015042706/b/Aifang_Web_Loupan_List_ListIndex.js
http://tracklog.ooxx.com/referrer_ooxx_pc.js
http://ifx.fang.ooxx.com/s?p=918&c=14&o=1&st=ajk
http://ifx.fang.ooxx.com/s?p=2000&c=14&r=0&sr=0&pa=&o=1&t=&st=ajk
http://pic1.ajkimg.com/display/xinfang/c43a03221d9fd83d6b409f31909ce19a/160x120.jpg
http://chart.aifcdn.com/average/price/city/?id=14&w=210&h=100&limit=6&date=20150428025144&logo=1
http://ifx.fang.ooxx.com/s?p=2001&c=14&o=1&st=ajk
  ......

另一个例子 netsniff.js 实现了将抓捕到的 网络请求导出成 HAR 格式然后可视化分析,有兴趣的同学可以参考这个官方的例子。

注意:

(1)phantomjs 的 page.settings.resourceTimeout 只能用于当前页面父请求的超时控制,并不能用于子请求的超时控制,这样当一个页面上百个请求有一个请求阻塞了,会导致整个请求卡死,好在如果它的子请求是异步的,你可以选择中断请求,获取已有的数据:

timeout 3 phantomjs netlog.js http://bj.fang.ooxx.com/|grep tracklog

(2)尽管 phantomjs 到了 2.0 已经相对成熟了,但部分文档和API功能还不完善,比如 evaluateJavaScript 的文档不完善,函数貌似还有 bug:

var webPage = require(‘webpage‘);
var page = webPage.create();

function add(arg1, arg2) {
	console.log(arg1 * arg2);
};
add(2, 3);
page.evaluateJavaScript(‘	function add(arg1, arg2) {		console.log(arg1 * arg2);	};	add(2, 3);‘);
phantom.exit();

//结果
6
SyntaxError: Expected token ‘)‘

  phantomjs://webpage.evaluate():1 in evaluateJavaScript
SyntaxError: Expected token ‘)‘

  phantomjs://webpage.evaluate():1 in evaluateJavaScript

4、Python 下的 PhantomJS:ghost.py

其实 Python 下的 ghost.py 和 PhantomJS 没有关系,这里只是对不熟悉 JS 的同学推荐下。

如果要实现第三节中的例子,ghost.py 也能做到,而且整体功能和 PhantomJS 类似:

# coding=utf-8
# 测试utf-8编码
from multiprocessing.pool import Pool
import sys

reload(sys)
sys.setdefaultencoding(‘utf-8‘)

from ghost import Ghost
import time

def requestUrl(url):
    resultStr = url + "\n"
    t1 = time.clock()
    ghost = Ghost()
    try:
        page, resources = ghost.open(url, wait=True, timeout=30)
        REQ_FOUND_FLAG = 0
        for index, trackReq in enumerate([res.url for res in resources if "tracklog" in res.url]):
            resultStr = resultStr + str(index) + "\t" + trackReq + "\n"
            REQ_FOUND_FLAG = 1
        if REQ_FOUND_FLAG == 0:
            resultStr = resultStr + "requests not found tracklog‘s URL: " + url + "\n"
    except Exception, e:
        resultStr = resultStr + str(e) + ": " + url + "\n"
    ghost.exit()
    t2 = time.clock()
    resultStr = resultStr + str(t2 - t1) + ": " + url + "\n"
    print resultStr + "-----------------------" + "\n"

if __name__ == "__main__":
    ts = time.time()
    urls = [
        ‘http://bj.ooxx.com/test/‘,
        ‘http://bj.ooxx.com/‘,
        ‘http://bj.ooxx.com/job.shtml‘,
        ‘http://bj.ooxx.com/chuzu/‘,
        ‘http://bj.ooxx.com/ershoufang/‘,
        ‘http://bj.fang.ooxx.com/?from=58_home_top‘,
        ‘http://bj.ooxx.com/ershouche/‘,
        ‘http://che.ooxx.com/‘,
        ‘http://bj.ooxx.com/sale.shtml‘,
        ‘http://bj.ooxx.com/dog/‘,
        ‘http://bj.ooxx.com/huangye/‘,
        ‘http://pic2.ooxx.com/m58/app58/m_static/home.html‘,
        ‘http://bangbang.ooxx.com/jc_pc_homepage_3.html‘,
        ‘http://jinrong.ooxx.com/k?from=58_index_ss‘,
        ‘http://about.ooxx.com/hr/‘
    ]

    p = Pool(4)
    p.map(requestUrl, urls)
    print("cost time is: {:.2f}s".format(time.time() - ts))

//结果:
C:\Python27\python.exe F:/sourceDemo/test.py
http://bj.ooxx.com/test/
requests not found tracklog‘s URL: http://bj.ooxx.com/test/
0.585803057247: http://bj.ooxx.com/test/
-----------------------

http://bj.ooxx.com/
requests not found tracklog‘s URL: http://bj.ooxx.com/
0.619204294693: http://bj.ooxx.com/
-----------------------

http://bj.ooxx.com/job.shtml
0	http://tracklog.ooxx.com/referrer4.js
1	http://tracklog.ooxx.com/referrer4.js
2	http://tracklog1.ooxx.com/pc/empty.js.gif?fromid=referrer4&site_name=58&tag=pvstatall&referrer=&type=index&post_count=-1&_trackParams=NA&version=A&loadtime=376&window_size=614x454&trackURL={‘new_uv‘:‘1‘,‘new_session‘:‘1‘,‘init_refer‘:‘‘,‘GTID‘:‘14301578423960.8530509551055729‘,‘cate‘:‘9224‘,‘area‘:‘1‘,‘pagetype‘:‘index‘,‘GA_pageview‘:‘/index/zhaopin/job/‘}&rand_id=0.2580734915100038
1.19415236255: http://bj.ooxx.com/job.shtml
-----------------------
......

虽说 ghost.py 整个功能和 PhantomJS 类似,但它的兼容性还是要差一大截:

(1)请求没有优化,对于页面上多个相同的引用请求,ghost.py 会老老实实的请求多次,而不会只请求一次。

(2)对于 js 的异步代码和函数封装的执行,兼容性不够,无法捕获请求或执行,如下两种写法在 ghost 下都有问题:

</script><script src="//tracklog.ooxx.com/referrer_ooxx_pc.js" type="text/javascript" async defer></script>

<script type="text/javascript">
readyToDo("$",function(){
  $.getScript(‘http://tracklog.ooxx.com/referrer4.js‘);
});
</script>

(3)和 PhantomJS 一样,ghost 也存在请求超时控制不够友好的问题,但 ghost 的问题似乎更严重,不请求完成就拿不到数据。

好了,本文就介绍 PhantomJS 到这里,主要通过一个实际的例子来展示 PhantomJS 的强大功能与特性,而在实际的 web 自动化测试或者爬虫需求中,它的一些其它特性我们或许恰好就能用得上~

5、Refer:

[1] PhantomJS:基于WebKit、开源的服务器端JavaScript API

http://www.infoq.com/cn/news/2015/01/phantomjs-webkit-javascript-api

[2] phantomjs not waiting for “full” page load

http://stackoverflow.com/questions/11340038/phantomjs-not-waiting-for-full-page-load

[3] phantomJS webpage timeout

http://stackoverflow.com/questions/16854788/phantomjs-webpage-timeout

http://t.cn/RARvSI4

[4] 有没有能解析js的库啊?

http://segmentfault.com/q/1010000000533061

[5] java调用phantomjs采集ajax加载生成的网页

http://blog.csdn.net/imlsz/article/details/24325623

[6] 使用Selenium和PhantomJS解析带JS的网页

http://smilejay.com/2013/12/try-phantomjs-with-selenium/

[7] PhantomJS快速入门教程

http://duchengjiu.iteye.com/blog/2201868

[8] PhantomJS API

http://phantomjs.org/api/

[9] Ghost.py

http://carrerasrodrigo.github.io/Ghost.py/

http://jeanphix.me/Ghost.py/

时间: 2024-11-05 18:50:51

Web 自动化测试与智能爬虫利器:PhantomJS 简介与实战的相关文章

selenium3 web自动化测试框架 三:Unittest介绍及项目实战中的运用

unittest介绍及运用,可以参考之前写的文章,除了未结合web自动化演示,基础知识都有了 https://www.cnblogs.com/wuzhiming/p/8858305.html unittest在自动化中的基础使用 下例演示用例的运行 # -*- coding:utf-8 -*- import unittest from selenium import webdriver from business.register_business import RegisterBusiness

Python爬虫利器四之PhantomJS的用法

前言 大家有没有发现之前我们写的爬虫都有一个共性,就是只能爬取单纯的html代码,如果页面是JS渲染的该怎么办呢?如果我们单纯去分析一个个后台的请求,手动去摸索JS渲染的到的一些结果,那简直没天理了.所以,我们需要有一些好用的工具来帮助我们像浏览器一样渲染JS处理的页面. 其中有一个比较常用的工具,那就是 PhantomJS Full web stack No browser required PhantomJS is a headless WebKit scriptable with a Ja

Python爬虫利器:Selenium的用法

本文和大家分享的主要是python 爬虫 利器Selenium的相关内容,一起来看看吧,希望对大家 学习python爬虫有所帮助. Selenium  是什么?一句话,自动化测试工具.它支持各种浏览器,包括  Chrome , Safari , Firefox 等主流界面式浏览器,如果你在这些浏览器里面安装一个  Selenium  的插件,那么便可以方便地实现 Web界面的测试.换句话说叫  Selenium  支持这些浏览器驱动.话说回来, PhantomJS 不也是一个浏览器吗,那么  S

Python爬虫利器六之PyQuery的用法

前言 你是否觉得 XPath 的用法多少有点晦涩难记呢? 你是否觉得 BeautifulSoup 的语法多少有些悭吝难懂呢? 你是否甚至还在苦苦研究正则表达式却因为少些了一个点而抓狂呢? 你是否已经有了一些前端基础了解选择器却与另外一些奇怪的选择器语法混淆了呢? 嗯,那么,前端大大们的福音来了,PyQuery 来了,乍听名字,你一定联想到了 jQuery,如果你对 jQuery 熟悉,那么 PyQuery 来解析文档就是不二之选!包括我在内! PyQuery 是 Python 仿照 jQuery

Sahi ---实现 Web 自动化测试

Sahi 是 Tyto Software 旗下的一个基于业务的开源 Web 应用自动化测试工具.Sahi 运行为一个代理服务器,并通过注入 JavaScript 来访问 Web 页面中的元素.Sahi 支持 HTTPS 并且独立于 Web 站点,简单小巧却功能强大.它相对于 Selenium 等自动化测试工具,在动态 ID 元素查找和隐式页面等待处理等方面具有一定的优势.选择 Sahi 工具来实现具体 Web 项目的自动化测试是一个很不错的选择. Web 测试背景 随着 Web 技术和互联网的发

使用 Sahi 实现 Web 自动化测试

Sahi 是 Tyto Software 旗下的一个基于业务的开源 Web 应用自动化测试工具.Sahi 运行为一个代理服务器,并通过注入 JavaScript 来访问 Web 页面中的元素.Sahi 支持 HTTPS 并且独立于 Web 站点,简单小巧却功能强大.它相对于 Selenium 等自动化测试工具,在动态 ID 元素查找和隐式页面等待处理等方面具有一定的优势.选择 Sahi 工具来实现具体 Web 项目的自动化测试是一个很不错的选择. Web 测试背景 随着 Web 技术和互联网的发

Python爬虫利器二之Beautiful Soup的用法

上一节我们介绍了正则表达式,它的内容其实还是蛮多的,如果一个正则匹配稍有差池,那可能程序就处在永久的循环之中,而且有的小伙伴们也对写正则表达式的写法用得不熟练,没关系,我们还有一个更强大的工具,叫Beautiful Soup,有了它我们可以很方便地提取出HTML或XML标签中的内容,实在是方便,这一节就让我们一起来感受一下Beautiful Soup的强大吧. 1. Beautiful Soup的简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官

Web自动化测试工具调研

背景 Web自动化测试越来越被重视, 因为现在Web已经是工程化的状态. 如何通过工具测试, 保证Web开发的质量,提升开发效率,是Web工具的诞生的来由. Web测试分为以下几个方面: 1. 界面测试 测试界面是否正常,这是前端测试最基础的环节. 2. 功能测试 测试功能操作是否正常,由于涉及交互,这部分测试比界面测试会更复杂 3. 性能测试 页面性能越来越受到关注,并且性能需要在开发过程中持续关注,否则很容易随着业务迭代而下降. 4. 安全性测试 测试Web界面和WebServer的安全性,

开源的网络爬虫以及一些简介和比较

转 目前网络上开源的网络爬虫以及一些简介和比较 目前网络上有不少开源的网络爬虫可供我们使用,爬虫里面做的最好的肯定是google ,不过google公布的蜘蛛是很早的一个版本,下面是几种开源的网络爬虫的简单对比表: 下面我们再对Nutch.Larbin.Heritrix这三个爬虫进行更细致的比较: Nutch 开发语言:Java http://lucene.apache.org/nutch/ 简介: Apache的子项目之一,属于Lucene项目下的子项目. Nutch是一个基于Lucene,类