如何通过 CasperJS 从具有特定 class 的元素中获取 href?

How to get hrefs from from elements with a certain class through CasperJS?

我有一个包含以下格式信息的网页:

<p>
    <a class="class1" href="href1">text1</a>
    text2
</p>

<p>
    <a class="class1" href="href2">text1a</a>
    text2a
</p>

使用 CasperJS,我需要获取包含在具有 class1 的元素中的所有信息的数组,格式如下:

href1
text1
text2

href2
text1a
text2a

我试过使用此代码:

var casper = require('casper').create();
casper.start('url', function() {
    require('utils').dump(this.getElementsAttribute('div[class="class1"]', 
          'class'));
});
casper.run();

但是,我只得到了一个“[]”作为答案。

谁能帮我找出代码中的错误?

div[class="class1"] 作为选择器无法工作,因为您的标记中没有任何具有 class1 class 的 <div> 元素。您可以尝试以下方法,但不会让您走得太远:

this.getElementsAttribute('a.class1', 'href');

在页面上下文中构建对象数组

仅使用 CasperJS 函数执行此操作很难并且可能容易出错。通过遍历所有 link 并获取您需要的部分,可以更容易地做到这一点。

casper.then(function(){
    var info = this.evaluate(function(){
        var links = document.querySelectorAll(".class1");
        // iterate over links and collect stuff
        return Array.prototype.map.call(links, function(link){
            return {
                href: link.href,
                hrefText: link.textContent.trim(),
                afterText: link.parentNode.childNodes[2].textContent.trim()
            };
        });
    });
    require('utils').dump(info);
});

这是如何工作的:

您可以通过查询所有带有 class1 的所有元素来获取所有 link。由于querySelectorAll()的结果不是一个数组,而是一个类似数组的NodeList,所以不能直接在上面使用.map()

每个 link 都有一个 href 属性 和一个 textContent 属性。 link 之后的文字有点棘手。您首先需要获取 link (<p>) 的父节点,然后尝试通过访问 childNodes 属性 来获取 link 之后的 TextNode。 =32=] 可能必须使用

childNodes[2] 而不是 childNodes[1],因为第一个 (childNodes[0]) 可能是一个包含空格的 TextNode,因此它之后的所有内容都会移动。

在页面上下文中构建单个字符串

您也可以遍历它以获取文本表示形式:

casper.then(function(){
    var info = this.evaluate(function(){
        var links = document.querySelectorAll(".class1");
        // iterate over links and collect stuff
        return Array.prototype.map.call(links, function(link){
            return [
                link.href,
                link.textContent.trim(),
                link.parentNode.childNodes[2].textContent.trim()
            ].join('\n');
        }).join('\n\n');
    });
    this.echo(info);
});

工作原理:

JavaScript 数组有一个 join() function。它可以使用指定的分隔符连接每个元素。


请记住,页面上下文 (evaluate()) 是沙盒化的。 documentation 表示:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!