本文翻译自这篇文章。
用CasperJS浏览页面比用PhantomJS更加方便和直观。
例如,先后打开webpage A,然后webpage B
用CasperJS的话,你可以这样写:
casper.start('URL of website A', function(){
console.log('Started');
});
casper.thenOpen('URL of website B', function(){
console.log('Started');
});
casper.then(function(){
this.evaluate(function(){
//Your code here
})
})
casper.run();
所以,用CasperJS可以非常简单地打开A站点,然后B站点。
关键在于这样写之后,网站B不会在网站A完全加载完成前打开。
这是个很好的功能,而且并没有在PhantomJS中实现。
如果你使用PhantomJS,你必须通过监听内容加载相关的事件来处理。
我们可以看下,如果用PhantomJS来完成同样功能需要怎么实现:
var steps=[];
var testindex = 0;
var loadInProgress = false;//This is set to true when a page is still loading
var clientRequests = new DRequest();
console.log("Initialization successful");
steps=[
function (){//Step 1 - Load Code Epicenter
console.log("Request a website and wait for website to load");
clientRequests.sendRequest("http://photo-epicenter.com");
},
function(){//STEP 2 - After page load, parse results. DO NOT CALL readResponse() IN STEP ONE, because our RESULT might be empty
console.log("Website loaded, read response");
clientRequests.readResponse();
var fs = require("fs");
console.log("Write data to file");
fs.write("website.html",clientRequests.getResponse(),"w");
}
];
//Start interval to read website content
interval = setInterval(executeRequestsStepByStep,2000);
function executeRequestsStepByStep(){
if (loadInProgress == false && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
phantom.exit();
}
}
/**
* These listeners are very important in order to phantom work properly. Using these listeners, we control loadInProgress marker which controls, weather a page is fully loaded.
* Without this, we will get content of the page, even a page is not fully loaded.
*/
clientRequests.phantomPage.onLoadStarted = function() {
loadInProgress = true;
console.log(loadInProgress);
console.log("Loading started");
};
clientRequests.phantomPage.onLoadFinished = function() {
loadInProgress = false;
console.log("Loading finished");
};
clientRequests.phantomPage.onConsoleMessage = function(msg) {
console.log(msg);
};
这将需要更多的代码,需要指出的是,这代码是前作者写的。
也许有更好的方案,但是,请相信我,这代码已经近乎优秀。
如果你想做的更多,不只是普通的从A页面到B页面,这代码就会变得更加复杂。并使得代码的维护成为一个噩梦。
两个库都会在发往后续请求时,将已经收到的cookie附加上去。
这一点对于登入之后的页面爬取非常有用。
很明显,CasperJS使用更为直观的语法会让你更加容易的维护你的脚本。同时,CasperJS拥有很多有用的功能,比如函数thenClick,它将元素的xpath作为第一个参数,这一点在你想点击菜单项时非常有用。通过chrome你可以取到元素的xpath值,只需要将它复制给CasperJS脚本。CasperJS脚本会模拟点击事件,你就会被重定向到希望的页面。如果你需要修改脚本让其和其他网站一起工作,你只需要修改xpaths。
在CasperJS中有很非常方便而且在phantomjs中没有实现的函数,参考这些API
在我们讨论PhantomJS时,这是一个热门话题,只少有20片文章在讨论怎么使用PhantomJS 来下载文件,有两个可行的方法:
* 在你的evaluate函数里调用ajax 请求下载,然后编码你的文件,然后你再将内容返回给PhantomJS脚本。
* 你可以使用在GitHut上没有编译的PhantomJS代码。
这两种办法都不能100%保证文件能正常下载,并且还有一个问题,当你不想保存下载的文件文件系统时(比如你不允许保存下载的数据到你的电脑上),想通过PhantomJS来完成几乎是不可能的。我的建议是,不要使用PhantomJS 来下载文件。
通过CasperJS,文件下载是非常容易的,因为CasperJS 提供下载的函数用来把文件下载到文件系统,或者对你想处理而不想保存的文件湖北续进行base64编码。
下面是base64编码的例子:
casper.start('http://www.google.fr/', function() {
base64logo = this.base64encode('http://www.google.fr/images/srpr/logo3w.png');
});
casper.run(function() {
this.echo(base64logo).exit();
});
下面这个例子演示如何通过CasperJS来下载csv文件而不把文件保存到文件系统:
var casper = require(‘casper’).create();
casper.start("http://captaincoffee.com.au/dump/", function() {
this.echo(this.getTitle())
});
casper.then(function(){
var url = 'http://captaincoffee.com.au/dump/csv.csv';
require('utils').dump(this.base64encode(url, 'get'));
});
casper.run();
PhantomJS和CasperJS都能完成不错的工作,但是你如果可以选择两者中的一个,我建议你使用CasperJS,因为你将会得到更好至少同样好的效果而不需要太多的付出。