我想遍历来自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。
答案 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'));
});