setTimeout在Phantom.js中

下面的代码希望Phantom.js加载页面,点击一个button,然后等待5秒钟,然后返回页面的HTML代码。

问题:但是使用setTimeout()创build5秒的延迟会导致page.evaluate函数将null返回给callback函数,而不是HTML。

 myUrl = 'http://www.google.com' var phantom = Meteor.npmRequire('phantom') phantom.create = Meteor.wrapAsync(phantom.create) phantom.create( function(ph) { ph.createPage = Meteor.wrapAsync(ph.createPage) ph.createPage(function(page) { page.open = Meteor.wrapAsync(page.open) page.open(listingUrl, function(status) { console.log('Page loaded') page.evaluate = Meteor.wrapAsync(page.evaluate) page.evaluate(function() { // Find the button var element = document.querySelector( '.search-btn' ); // create a mouse click event var event = document.createEvent( 'MouseEvents' ); event.initMouseEvent( 'click', true, true, window, 1, 0, 0 ); // send click to element element.dispatchEvent( event ); // Give page time to process Click event setTimeout(function() { // Return HTML code return document.documentElement.outerHTML }, 5000) }, function(html) { // html is `null` doSomething() }) }) }) }) 

Meteor.setTimeout()replacesetTimeout()会导致另一个错误:

 phantom stdout: ReferenceError: Can't find variable: Meteor 

page.evaluate()是PhantomJS的沙盒页面上下文。 它无法访问外部定义的variables。 如果您需要超时,那么您需要对page.evaluate()进行两次调用,因为您无法从asynchronous函数( 解释 )返回任何内容:

 page.evaluate(function() { ... element.dispatchEvent( event ); }, function() { setTimeout(function() { page.evaluate(function() { return document.documentElement.outerHTML }, function(html) { doSomething() }) }, 5000) }) 

您可以通过直接访问以下定义的内容来缩短代码,而不是使用第二个page.evaluate()调用:

 setTimeout(function() { page.get("content", function(content) { doSomething() }) }, 5000) 

这不是一个很好的解决scheme,但如果你想要做的就是button点击和表单提交处理页面更改。 只需在page.open()之外声明函数variables,然后在里面为它们分配页面评估函数。 onLoadFinished将在页面重新加载之后调用button点击的变化,然后您可以再次评估。

 var loadInProgress = false, jurl = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js', page = require('webpage').create(); // declare variables outside page.open and assign them later inside var evalPageFunc; // assign callbacks which will be called by phantom page.onLoadStarted = function() { loadInProgress = true; console.log('load started'); }; page.onLoadFinished = function() { loadInProgress = false; console.log('load finished'); if (evalPageFunc) { // since the page has loaded we can safely evaluate it var mydata = evalPageFunc(); console.log(mydata); if (!mydata.havemore) { phantom.exit(); // or next url } } }; page.open(url, function(status) { page.includeJs(jurl, function(){ // define your page evaluating functions evalPageFunc = function(){ return page.evaluate(function() { var datafromhtml = {}, havemoretoclick = true; // get your data and perform clicks if you want to // datafromhtml.somedata = $('stealme').text(); // $("clickme").click(); return { havemore: havemoretoclick, data: datafromhtml }; }); } var k = evalPageFunc(); }); }); 

它不漂亮,但它的作品。