使用CasperJS从querySelectorAll遍历NodeList

时间:2015-02-13 22:11:18

标签: javascript phantomjs casperjs selectors-api

我想遍历来自querySelectorAll的NodeList。

无法正常工作

var nodelist = this.evaluate(function() {
    return document.querySelectorAll('tr.firstrow');
});

this.echo("nodelist.length=" + nodelist.length);

for (var i=0; i<nodelist.length; i++) {
    this.echo("i=" + i);
    line = nodelist[i];
    this.echo("Line: " + line.innerText);
}

我得到的是:

nodelist.length=3
i=0
this it the first line 
i=1

i = 1后,输出冻结。对于第一个项目&#34; for&#34;循环按预期运行,但随后不会继续。当我在浏览器控制台中运行querySelectorAll时,我会看到所有三个不同的项目。

在这里,我发现了一种有效的方法:

工作原理

var nodelist = this.evaluate(function() {
    var nodes = document.querySelectorAll('tr.firstrow');
    var array = [nodes[0].innerText,nodes[1].innerText,nodes[2].innerText];
    return array;
});
this.echo("nodelist.length=" + nodelist.length);
for (var i=0; i<nodelist.length; i++) {
    this.echo("i=" + i);
    line = nodelist[i];
    this.echo("Line: " + line);
}

但这很不方便。

然后我尝试将此节点列表转换为数组。但是这种方法也没有用,因为评估函数的返回值丢失了。

无法正常工作

var nodelist=this.evaluate(function() 
{
console.log("...evaluate()");
var fr_n=document.querySelectorAll('tr.firstrow');
console.log("fr_n.length:" + fr_n.length);

var fr_a=Array.prototype.slice.call(fr_n);

console.log("fr_a.length:" + fr_a.length);
console.log("typeof fr_a:" + typeof fr_a);
console.log("fr_a[0]=" + fr_a[0].innerText);
console.log("fr_a[1]=" + fr_a[1].innerText);
console.log("fr_a[2]=" + fr_a[2].innerText);

return fr_a;

});

this.echo("nodelist.length=" + nodelist.length);

if (Array.isArray(nodelist))
{
 this.echo ("nodelist is array");
}
else
{
 this.echo ("nodelist is not array");
}

for (var i=0; i<nodelist.length; i++)
{
 this.echo("i:" + i);
 line = nodelist[i];
 this.echo("Line: " + line); 
};

产生以下输出:

remote console.log: ...evaluate()
remote console.log: fr_n.length:3
remote console.log: fr_a.length:3
remote console.log: typeof fr_a:object
remote console.log: fr_a[0]=This is the first line I want to see 
remote console.log: fr_a[1]=This is the second line I want to see
remote console.log: fr_a[1]=This is the third line I want to see
nodelist.length=0
nodelist is array
[info] [phantom] Done 4 steps in 6943ms

我希望nodelist.length为3而不是0。

2 个答案:

答案 0 :(得分:2)

PhantomJS'page.evaluate()函数是沙盒页面上下文。传递的所有内容必须基本上进行字符串化并再次解析。

  

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

     

闭包,函数,DOM节点等不起作用!

这意味着您无法从页面上下文中获取元素,但您可以在页面上下文中构建它们的表示并将其传递到外部。

您可能想要这些元素的textContent。您可以使用CasperJS函数getElementsInfo(),它为每个元素提供text属性。然后,您只能过滤此属性的信息:

var texts = casper.getElementsInfo('tr.firstrow').map(function(tr){
    return tr.text;
});

如果它不是您所追求的文本,则必须在页面上下文中找到另一个表示或遍历NodeList(在casper.evaluate()内)。

答案 1 :(得分:0)

尝试将NodeList(由querySelectorAll返回)转换为Array

var nodelist=this.evaluate(function() {
    return Array.prototype.slice.call(document.querySelectorAll('tr.firstrow'));
});