我正在尝试使用CasperJS从网站上抓取不同网页的HTML链接。
在我的浏览器地址栏(Firefox / Chrome)中,此功能完美无缺,并打开了我正在寻找的所有链接。
javascript:document.querySelectorAll('a[href^="/page"]').click();
但是,当我尝试使用下面的代码在CasperJS上运行类似的东西时,我会遇到很多与上述不一致的错误。
var pageNodes = this.evaluate(function() {
return document.querySelectorAll('a[href^="/page"]');
});
console.log(typeof(pageNodes)); //Shows object
console.log(pageNodes.length); //Shows 11, which is correct
var links = [];
for(var i = 0; i < pageNodes.length; i++) {
console.log(i);
console.log(pageNodes[i].href);
links.push(pageNodes[i].href);
}; //pageNode[0].href shows the correct link. pageNode[1] is a null for some reason when it shouldn't be!
我也尝试了上面的数组原型,但结果相同!任何人都可以帮我弄清楚什么是错的?
var pageArray = this.evaluate(function(pageNodes) {
return Array.prototype.splice(pageNodes, 0);
}); //Gives the same problem, since pagesNodes[1] is null.
答案 0 :(得分:0)
PhantomJS有两个上下文,由于CasperJS是建立在它之上的,因此它具有相同的限制。这意味着对页面上下文的访问是沙箱化的,您无法传递任意对象。 documentation说明了这一点:
注意:
evaluate
函数的参数和返回值必须是一个简单的原始对象。经验法则:如果它可以通过JSON序列化,那就没关系了。闭包,函数,DOM节点等将不工作!
如果要访问每个链接的href属性,则必须构建一个可以传递到外部或只从页面上下文打印的基本对象:
casper.on("remote.message", function(msg){
this.echo("remote> " + msg);
});
var links = this.evaluate(function() {
var pageNodes = document.querySelectorAll('a[href^="/page"]');
var links = [];
for(var i = 0; i < pageNodes.length; i++) {
console.log(i);
console.log(pageNodes[i].href);
links.push(pageNodes[i].href);
};
return links;
});
require("utils").dump(links);