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(); }); });
它不漂亮,但它的作品。