PhantomJS is a headless WebKit scriptable with a JavaScript API.
PhantomJS是一个可编程的无头浏览器.
无头浏览器:一个完整的浏览器内核,包括js解析引擎,渲染引擎,请求处理等,但是不包括显示和用户交互页面的浏览器。
PhantomJS的适用范围就是无头浏览器的适用范围。通常无头浏览器可以用于页面自动化,网页监控,网络爬虫等:
我们将使用一个较简单的例子来演示phantomJS如何安装,使用。并用一个稍微复杂的例子来演示Phantom如何做到网页自动化。
这里的hello world就是打开http://www.baidu.com/并且截屏;
想要使用PhantomJS,我们需要搭建PhantomJS的环境.
我们可以去官网上下载最新的PhantomJS http://phantomjs.org/;
phantomjs下载后可以直接解压使用了
双击phantomjs.exe就可以看到一个控制台。这时已经进入了PhantomJS的世界
运行的效果:
var webPage = require('webpage');
var page = webPage.create();
page.open("http://www.baidu.com", function start(status) {
page.render('baidu.jpeg');
phantom.exit();
});
编写这个简单的程序,保存为helloWorld.js,然后我们在控制台内输入
phantomjs.exe helloWorld.js
就可以看到运行效果:
var webPage = require('webpage');
var page = webPage.create();
这一句是告诉Phantomjs 我们需要webpagae模型,第二句是创建具体是使用对象page。目前Phantom提供的模型有:
接下来
page.open("http://www.baidu.com", function start(status) {...});
这一句实际上是告诉PhantomJS我们要打开的页面是http://www.baidu.com,并在打开完成后调用start函数。这里是回调的写法。在所有的PhantomJS的对象内。函数都是回调的。
page.render('baidu.jpeg');
phantom.exit();
render这个函数是表示将当前页面绘制回来,并保持到baidu.jpeg内。
Phantom.exit()就是退出程序。
phantome.exe helloWorld.js
使用PhantomJS来执行helloWorld.js这个文件。实际上,在我们执行JS的时候,我们可以指定一些参数。比较重要的有:
在本例中我们只使用了PhantomJS中最简单的函数。你可以在这里找到Phantoms详细的说明文档:http://phantomjs.org/api/;
在我们的上个例子中,我们已经可以打开百度了,那么为何不更近一步呢。假设我们现在需要获取到百度对一个关键词的搜索结果。怎么办?
我们打开baidu的搜索页,可以发现.实际上baidu的搜索结果现在已经变成了动态加载的了;
我们当然可以抓包分析下baidu的执行流程,但是如果他修改了。我们的改动成本肯定相对较大。
那么 我们能不能使用PhantomJS来获取到Baidu搜索后的结果呢?
如果使用Phantom,我们只需要在baidu首页的输入框中输入helloworld,然后点击百度一下来实现搜索功能,并且将baidu搜索出的连接地址保持到一个名为url.txt的文件中即可。
程序如下:
var webPage = require('webpage');
var page = webPage.create();
var fs = require('fs');
//上文介绍的文件系统 输出文件需要
var path = 'url.txt';
//在PhantomJS中 执行JS函数的时候是不能直接使用Phantom的方法的。需要hook住alert方法,再使用alert来输出
page.onAlert = function(msg) {
fs.write(path, msg, "w");
};
//引入jquery 让我们的操作更方便。
page.injectJs("jquery-1.6.1.min.js");
page.open("http://www.baidu.com", function(status) {
//当打开成功后。输入检索内容并点击搜索
//注意这两个按钮的的ID还是需要人为去看一下的
if ( status === "success" ) {
page.evaluate(function(text) {
$("#kw1").val(text);
$("#su1").click();
}, "hello world");
}
});
//我们需要获取资源加载成功的方法并重写
//更多的phantom的方法可以参考官方链接。
page.onResourceReceived = function (res,network) {
if (res.stage == "end") {
//我们仍然需要知道baidu搜索后的结束条件
if (res.url.indexOf("b1.bdstatic.com")>=0) {
//获取左边的所有标签并打印出text和链接
page.evaluate(function() {
var result="";
$("#content_left a").each(function(){
result=result+$(this).text()+" "+$(this).attr("href")+"\n";
});
alert(result);
});
page.render('baidu.jpeg');
phantom.exit();
}
}
};
执行这个脚本。我们可以发现本地文件夹下生成了一个url.txt并且生成了一个点击后的图片
PhantomJS提供了一系列的API来让我们编程控制。这些API看似可以帮我们实现一些不易实现的功能。如网页自动化,动态爬虫等等。但是真的有这么美好么?
来让我们看下phantomJS到底有哪些坑:
虽然PhantomJS并没有那么的完美,但是他也提供了一套自动化页面及ajax爬虫的方案。
根据以往的经验,不建议完全使用PhantomJS来进行开发。而是使用Phantom来实现一些其他语言不方便实现的功能,然后再其他语言来调用。调用方式可以使用services或者是本地命令