考虑以下(工作)PhantomJS代码段,应该点击类whatever
的第一个元素:
page.evaluate(
function()
{
var a = document.querySelector(".whatever");
var e = document.createEvent('MouseEvents');
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
a.dispatchEvent(e);
waitforload = true;
}
);
我没有在类whatever
的所有元素上循环 - 问题当然不是循环本身,而是访问querySelectorAll
元素。
我被困在这里(我通过访问第一个元素来替换循环以便于调试;当然,必须有两个page.evaluate
调用,因为第二个元素将在循环中):
var aa = page.evaluate(
function()
{
return document.querySelectorAll(".whatever");
}
)
//for (i=0; i<aa.length; i++)
//{
page.evaluate(
function()
{
var e = document.createEvent('MouseEvents');
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
// aa[i].dispatchEvent(e);
aa[0].dispatchEvent(e);
waitforload = true;
}
);
//}
我尝试了多种变体,删除var
,为document.
添加前缀,尝试将aa
作为参数传递等等。没有任何效果(我可能错过了 正确的组合,但无论如何我明显错过了这里的基础。)
我不确定它是否与命名空间和变量范围有关(我是JS的新手)或问题来自querySelectorAll
输出(虽然我检查了数组的大小为了正确),因为我遇到了“ ReferenceError:找不到变量”和“ TypeError:'undefined'不是对象”错误。
欢迎任何提示。
答案 0 :(得分:2)
根据您的comment:
只需点击一下即可加载包含其他信息的框。盒子本身隐藏了其他按钮,因此我不知道在显示该框时单击另一个按钮会发生什么。我的猜测是,它将替换或替换上一个框。无论如何,我的目标是获得所有这些盒子。所以一开始我会尝试一个接一个地点击一切。
最简单的解决方案是检索.whatever
元素的数量并根据它进行迭代,但由于它需要一些页面交互而PhantomJS是异步的,因此您需要使用一些框架来运行一个步骤另一个。可以使用async,或者为此脚本创建类似的内容。
function clickInPageContext(selector, index){
page.evaluate(function(selector, index){
index = index || 0;
var e = document.createEvent('MouseEvents');
e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
var el = document.querySelectorAll(selector);
el[index].dispatchEvent(e);
}, selector, index);
}
var async = require("async"); // install async through npm
var selector = ".whatever";
var num = page.evaluate(function(sel){
return document.querySelectorAll(sel).length;
}, selector);
var steps = [];
for (var i = 0; i < num; i++) {
// the immediately invoked function looks bad, but is necessary,
// because JS has function level scope and this is executed long
// after the loop has finished
steps.push((function(i){
return function(complete){
clickInPageContext(selector, i);
setTimeout(function(){
clickInPageContext("someCloseButtonSelector"); // maybe also parametrized with i
setTimeout(function(){
complete();
}, 1000); // time to close
}, 1000); // time to open
};
})(i));
}
async.series(steps, function(){
console.log("DONE");
phantom.exit();
});
此测试取决于.whatever
元素的数量保持不变的前提。注意:async可以通过npm(本地)安装。并且可以在PhantomJS中使用。
另外,请参阅this question我做过类似的事情。