2014-11-06 26 views
0

上考虑以下(工作)PhantomJS一段代码,应该点击whatever类的第一个元素:循环并单击querySelectorAll清单,PhantomJS

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

是的,这与范围/沙箱非常相关。有多种解决方案。问题是这些点击是做什么的?加载一个新页面或只是改变页面的状态?如果是后者,你是否需要从相同的状态开始,或者如果你只是一个接一个地点击所有内容,那么是否可以? – 2014-11-06 16:22:22

+0

我当然不知道。一次点击就会加载一个包含额外信息的框该框本身隐藏了其他按钮,因此我不知道一旦显示该框时单击另一个按钮时会发生什么。我的猜测是,它将取代或在前面的框顶部。无论如何,我的目标是让所有这些盒子。所以一开始我会尝试点击一个接一个地点。 – 2014-11-06 16:55:07

回答

2

comment

One click loads a box with additional information. The box itself hides the other buttons, so I don't know what happens when one clicks on another button once the box is displayed. My guess is that it will either replace or come on top of the previous box. Anyway my goal is to get all of these boxes. So for a start I would try to click everything one after the other.

最简单的解决办法是检索.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元件数保持不变的前提。注意:可以通过npm(本地)安装异步。并且可以在PhantomJS中需要。
另外,请参阅this question,我在那里做了类似的事情。

+0

谢谢。我用评估和记录我需要的元素替换'clickInPageContext(“someCloseButtonSelector”)''。对于记录来说,为了使它工作,我必须将整段代码(在'var selector'下面)放在我之前进行单击和评估的地方 - 也就是说,作为“waitFor”子句的第二个参数的函数内容。 – 2014-11-07 16:26:55

+0

是的,我希望你做出这些改变。 – 2014-11-07 16:31:16

+0

噢,感谢关于'npm'的提示,我不知道。 – 2014-11-07 16:37:47