【问题标题】:How to use jQuery find() function with CasperJS?如何在 CasperJS 中使用 jQuery find() 函数?
【发布时间】:2015-01-22 06:23:38
【问题描述】:

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

类似这样的:

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

代码sn-p如下:

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 中实现这一点?

【问题讨论】:

    标签: javascript jquery testing phantomjs casperjs


    【解决方案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-th 父级(从 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() 函数是沙盒页面上下文。它的局限性在于必须将变量显式传递给它(完全阅读this),并且通常this 指的是页面的window 而不是casper。在您的情况下,您在map 回调中使用this,它将引用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));
    });
    

    【讨论】:

    • 我对 CasperJS 比较陌生。文档中没有明确说明对象和函数的范围。感谢您的详细解释。这是我真正需要的。这清除了很多东西。跨度>
    • 我在执行上述 sn-p 时收到此错误“TypeError:'undefined' is not a function (evalating 'e.find('h4.summary')')” jQuery 库包含在脚本中。有什么想法吗?
    • 谢谢,jQuery 有一个奇怪的map 语法。我使用$(this) 修复了它。为什么要使用 jQuery?使用原生 CasperJS 函数的方法更加简洁。
    • CasperJS 函数是否支持这个?基本上,我想链接定位器。(即类似 parentElement.find(childElement)。为什么我要这样做,因为我有多个父元素和这个让我避免使用索引。否则,我需要在所有子元素中提供完整的 css 路径以及索引(类似于这样的父级:nth-​​of-type(index) child)。这是我选择使用 jQuery 的主要原因.
    • 我不明白您为什么需要索引或完整的 CSS 路径。但是您还没有提供您的示例 HTML 以及您希望结果采用什么形式。由于您没有指定这一点,我的回答显示了一个可能的解决方案。顺便说一句,我刚刚修复了 jQuery 解决方案。一个函数中不可能有两个返回值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2010-12-07
    • 1970-01-01
    • 2018-10-01
    • 2023-02-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多