在CapserJS中使用document.querySelectorAll的正确方法是什么?

时间:2015-10-21 04:43:41

标签: javascript phantomjs casperjs

我正在尝试使用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. 

1 个答案:

答案 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);
相关问题