如何在CasperJS中使用jQuery find()函数?

时间:2015-01-22 06:23:38

标签: javascript jquery testing phantomjs casperjs

我想在CasperJS中的函数中执行与Cabybara类似的操作。我想获得父div并从子元素中检索文本。

这样的事情:

$('div.education').find('h4').text()
$('div.education').find('h1').text()

代码段如下:

casper.page.injectJs('/jquery-latest.min.js');
var links = casper.evaluate(function() {
    var elements = $('div.education');
    return elements.map(function(e){
           this.fetchText(casper.evaluate(function(){
                return e.find('h4.summary');
           }));
           this.fetchText(casper.evaluate(function(){
                return e.find('h1');
           }));
    });
});
casper.echo(links);

目前正在返回null。如何在CasperJS中实现这一目标?

1 个答案:

答案 0 :(得分:1)

$('div.education').find('h4')

应该在功能上等同于CSS选择器

'div.education h4'

如果要从这些节点获取文本,可以使用casper.fetchText(),但它会将所有文本连接成一个字符串。另一个有用的函数是casper.getElementsInfo(),因为它已经提供了text属性:

casper.then(function(){
    var h4Texts = this.getElementsInfo('div.education h4').map(function(h4){
        return h4.text;
    });
    var h1Texts = this.getElementsInfo('div.education h1').map(function(h1){
        return h1.text;
    });
    // do something with h4Texts and h1Texts
});

这个h4和h1文本在同一个父元素的两个不同列表中,可能不是你想要的。你仍然可以使用CasperJS的函数来实现使用CasperJS的XPath支持将h4和h1文本放在一起:

var x = require('casper').selectXPath;
casper.then(function(){
    var parents = this.getElementsInfo('div.education');
    var result = parents.map(function(divInfo, i){
        var h4Texts = this.getElementsInfo(x('(//div[contains(@class,'education')])['+(i+1)+']//h4')
            .map(function(h4){
                return h4.text;
            });
        var h1Texts = this.getElementsInfo(x('(//div[contains(@class,'education')])['+(i+1)+']//h1')
            .map(function(h1){
                return h1.text;
            });
        return {h1: h1Texts, h4: h4Texts};
    });

    var h1Texts = this.getElementsInfo('div.education h1').map(function(h1){
        return h1.text;
    });
    // do something with `result`
});

说明

  • //div[contains(@class,'education')]返回父元素的节点列表
  • (//div[contains(@class,'education')])['+(i+1)+']获取i+1 - 父(计数从1开始)和
  • (//div[contains(@class,'education')])['+(i+1)+']//h1(//div[contains(@class,'education')])['+(i+1)+']//h4找到同一父母的h1和h4后代。

您的代码存在多个问题。

casper.page.injectJs('/jquery-latest.min.js');中的文件名应为'./jquery-latest.min.js''jquery-latest.min.js' jquery与CasperJS脚本位于同一目录中。

然后,似乎你不理解页面上下文和外部casper上下文之间的区别。 casper.evaluate()函数是沙盒页面上下文。它有一些限制,必须明确地将变量传递给它(完全阅读this),通常this指的是页面的window而不是casper。在你的情况下,你在this回调中使用map,它将引用DOM节点的jQuery对象,而不是casper。此外,jQuery没有.fetchText()函数,因此会产生错误。页面上下文中也不提供casper,但您可以使用__utils__ module

所以你可以像这样编写脚本:

casper.page.injectJs('jquery-latest.min.js');
var links = casper.evaluate(function() {
    var elements = $('div.education');
    return elements.map(function(){
        return {
            h4: $(this).find('h4.summary').map(function(){
                return $(this).text();
            }),
            h1: $(this).find('h1').map(function(){
                return $(this).text();
            })
        };
    });
});
casper.echo(links);

最后,为了确保您看到所有问题,请注册remote.messagepage.error事件:

casper.on("remote.message", function(msg){
    this.echo("remote.msg: " + msg);
});

casper.on("page.error", function(pageErr){
    this.echo("page.err: " + JSON.stringify(pageErr));
});