如果页面是JS渲染的该怎么办呢?如果我们单纯去分析一个个后台的请求,手动去摸索JS渲染的到的一些结果,那简直没天理了。所以,我们需要有一些好用的工具来帮助我们像浏览器一样渲染JS处理的页面。

其中有一个比较常用的工具,那就是PhantomJS。

PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎。它原生支持多种web 标准:DOM 操作,CSS选择器,JSON,Canvas 以及SVG。因此可以比浏览器更加快速的解析处理js加载。

一、安装

1、首先下载PhantomJS。( 点击进入下载链接

2、下载后解压,将文件夹bin下的phantomjs.exe放在python安装目录的Script文件夹C:\Python27\Scripts下。起始这里是为了把phantomjs.exe的路径添加到环境变量,而python安装目录的Script文件夹路径,已经添加到了环境变量中,所以这里也就省略了。

3、在cmd中输

phantomjs -v

如果正常显示版本号,那么证明安装成功了。如果提示错误,那么检查python的环境变量是否设置。

二、基础内容

2.1、第一个程序

第一个程序当然是Hello World,新建一个 js 文件。命名为 helloworld.js

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

打开cmd,先cd到js文件夹所在的目录,再调用如下语句实现phantom运行js文件。
如我的js文件存储在D:\FFF文件夹下,依次执行下面的命令d:

cd \FFF
phantomjs helloworld.js

程序输出了 Hello,world!程序第二句话终止了 phantom 的执行。

注意:**phantom.exit();**这句话非常重要,否则程序将永远不会终止。

2.2、页面加载

可以利用 phantom 来实现页面的加载,下面的例子实现了页面的加载并将页面保存为一张图片。

将以下命令存储为pageload.js保存在你的文件夹中

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

首先创建了一个webpage对象,然后加载本站点主页,判断响应状态,如果成功,那么保存截图为 example.png

打开cmd,先cd到js文件夹所在的目录,再调用如下语句实现phantom运行js文件。

phantomjs pageload.js

2.3、测试页面加载速度

下面这个例子计算了一个页面的加载速度,同时还用到了命令行传参的特性。新建文件保存为 loadspeed.js。

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();
});

程序判断了参数的多少,如果参数不够,那么终止运行。然后记录了打开页面的时间,请求页面之后,再纪录当前时间,二者之差就是页面加载速度。

phantomjs loadspeed.js http://blog.cs.net/luanpeng825485697

运行结果

Loading http://blog.cs.net/luanpeng825485697
Loading time 8576 msec

这个时间包括JS渲染的时间,当然和网速也有关。

2.4、代码评估

利用 evaluate 方法我们可以获取网页的源代码。这个执行是“沙盒式”的,它不会去执行网页外的 JavaScript 代码。evalute 方法可以返回一个对象,然而返回值仅限于对象,不能包含函数(或闭包)

var url = 'http://www.baidu.com';
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();
});

以上代码获取了百度的网站标题。

三、屏幕捕获

因为 PhantomJS 使用了 WebKit内核,是一个真正的布局和渲染引擎,它可以像屏幕截图一样捕获一个web界面。因为它可以渲染网页中的人和元素,所以它不仅用到HTML,CSS的内容转化,还用在SVG,Canvas。可见其功能是相当强大的。

除了 png 格式的转换,PhantomJS还支持 jpg,gif,pdf等格式。

前面有使用介绍,这里就不介绍了。

其中最重要的方法便是 viewportSize 和 clipRect 属性。

viewportSize 是视区的大小,你可以理解为你打开了一个浏览器,然后把浏览器窗口拖到了多大。

clipRect 是裁切矩形的大小,需要四个参数,前两个是基准点,后两个参数是宽高。

var page = require('webpage').create();
page.viewportSize = { width: 1024, height: 768 };
page.clipRect = { top: 0, left: 0, width: 1024, height: 500 };

page.open('http://blog.cs.net/luanpeng825485697', function() {
  page.render('csdn.png');
  phantom.exit();
});

就相当于把浏览器窗口拖到了 1024×768 大小,然后从左上角裁切出了 1024×500 的页面。

四、网络监听

因为 PhantomJS 有网络通信的检查功能,它也很适合用来做网络行为的分析。

当接受到请求时,可以通过改写onResourceRequested和onResourceReceived回调函数来实现(接收到资源请求)和(资源接收完毕)的监听。例如

var url = 'http://www.525heart.com';
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);

运行结果会打印出所有资源的请求和接收状态,以JSON格式输出。

五、页面自动化处理

因为 PhantomJS 可以加载和操作一个web页面,所以用来自动化处理也是非常适合的。

5.1、DOM操作

脚本都是像在浏览器中运行的,所以标准的 JavaScript 的 DOM 操作和 CSS 选择器也是生效的。

例如下面的例子就修改了 User-Agent,然后还返回了页面中某元素的内容。

var page = require('webpage').create();
console.log('The default user agent is ' + page.settings.userAgent);
page.settings.userAgent = 'SpecialAgent';
page.open('http://blog.cs.net/luanpeng825485697', function(status) {
  if (status !== 'success') {
    console.log('Unable to access network');
  } else {
    var ua = page.evaluate(function() {
      return document.getElementById('blog_title').textContent;
    });
    console.log(ua);
  }
  phantom.exit();
});

运行结果首先打印出了默认的 User-Agent,然后通过修改它,请求验证 User-Agent 的一个站点,通过选择器得到了修改后的 User-Agent。

5.2、使用附加库

在1.6版本之后允许添加外部的JS库,比如下面的例子添加了jQuery,然后执行了jQuery代码。

var page = require('webpage').create();
page.open('http://blog.cs.net/luanpeng825485697', function() {
  page.includeJs("http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js", function() {
    page.evaluate(function() {
      $("button").click();
    });
    phantom.exit()
  });
});

引用了 jQuery 之后,我们便可以在下面写一些 jQuery 代码了。

六、Webpage对象

在前面我们介绍了 webpage 对象的几个方法和属性,其实它本身还有其它很多的属性。具体的内容可以参考

 Webpage

 Webpage用例

 官方实例