函数中的CasperJS querySelectorAll(变量)不返回任何结果

时间:2015-03-28 07:38:00

标签: javascript phantomjs casperjs selectors-api

我正在编写网站抓取工具,从ajax网站抓取一些特定内容,没有实际链接,只有可点击的文字。我现在只使用javascript大约一个星期,并且正在使用CasperJS,因为它会减少很多工作。

我发现的问题是,我正在编写多个功能,这些功能都做同样的事情,只是根据它所在的页面搜索不同的链接。 所以我有:

function getLinks() {
    var links = document.querySelectorAll('div.AjaxLink h3');
    return Array.prototype.map.call(links, function(link) {
        return link.innerText;
    });
}

通过以下方式运行:

casper.then(function() {
    var myLinks = this.evaulate(getLinks);
    /* ... link manipulation code code ... */
});

这很好用。我显然不想拥有六个只有不同查询字符串的函数。所以我想做的是:

function getLinks(findText) {
    var links = document.querySelectorAll(findText);
    return Array.prototype.map.call(links, function(link) {
        return link.innerText;
    });
}

然后我试图通过以下方式运行它:

casper.then(function() {
    var myLinks = getLinks('div.AjaxLink h3');
    /* ... link manipulation code code ... */
});

正确传入了findText变量,但看起来查询选择器总是返回一个空的NodeList。

我做错了什么? 文档 是在该函数中创建的空文档吗?

1 个答案:

答案 0 :(得分:6)

CasperJS建立在PhantomJS之上。 PhantomJS有两种情境。可通过evaluate()访问的沙盒页面上下文以及可访问requirephantom的外部上下文。奇怪的是,两个上下文都可以访问windowdocument,但document并不意味着外部上下文中的任何内容,因为DOM是空的。这就是querySelectorAll()找不到元素的原因。页面DOM只能通过evaluate()访问。

所以你需要在casper.evaluate()中执行你的功能。函数的附加参数传递给evaluate()而不是函数:

function getLinks(findText) {
    ...
}

casper.then(function() {
    var myLinks = this.evaluate(getLinks, 'div.AjaxLink h3'); // THIS
    ...
});

evaluate页面底部还有一个重要提示:

  

注意: evaluate函数的参数和返回值必须是一个简单的原始对象。经验法则:如果它可以通过JSON序列化,那就没关系了。

     

闭包,函数,DOM节点等将工作!