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

How to use jQuery find() function with 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 中实现这一点?

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

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

'div.education h4'

如果你想从这些节点获取文本,你可以使用 casper.fetchText(), but it will concatenate all text into a single string. Another useful function is casper.getElementsInfo() 因为它已经提供了文本 属性:

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')] returns父元素的节点列表,
  • (//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 脚本位于同一目录中。

那看来你没有理解page context和outer casper context的区别。 casper.evaluate() function is the sandboxed page context. It has the limitations that variables have to be explicitly passed into it (read this completely) and usually this refers to window of the page and not casper. In your case you use this inside of the map callback which will refer to the jQuery object of the DOM node and not casper. Also, jQuery doesn't have a .fetchText() function, so it will produce an error. casper is also not available in the page context, but you can use the __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.message and page.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));
});