2015-03-09 17 views
11

Aşağıdaki kod, Phantom.js'in sayfayı yüklemesini, bir düğmeyi tıklatıp sayfanın HTML kodunu döndürmeden önce 5 saniye beklemesini istiyor.setTimeout içinde Phantom.js

Sorun: Ancak 5 saniye gecikme oluşturmak için setTimeout() kullanarak HTML yerine geri arama işlevine null dönmek için page.evaluate işlevini neden olur. Meteor.setTimeout() ile setTimeout() değiştirilmesi

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() 

      }) 
     }) 
    }) 
}) 

başka hataya neden oluyor:

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

cevap

9

page.evaluate() PhantomJS ait korumalı sayfa bağlamı olduğunu. Dışarıda tanımlanan değişkenlere erişim yoktur. Eğer zaman aşımı gerekirse bir asenkron işlevinden şey döndüremez çünkü, o zaman, page.evaluate() iki çağrı yapmak (explanation) gerekir:

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

yerine ikinci page.evaluate() çağrıyı kullanmak yerine, kod alma kısalabilir doğrudan tanımlanan here olarak içeriğe erişmesini:

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

Bu harika bir çözüm değil ama yapmak istediğiniz tüm düğme tıklama ve form gönderimlerini sayfa değişiklikleri ele ise çalışır. Sadece page.open() dışındaki işlev değişkenlerini bildirin ve daha sonra içeride sayfa değerlendirme işlevlerini atayın. onLoadFinished, sayfanın düğmeye tıkladıktan sonra yeniden yüklendikten sonra çağrılacak ve daha sonra tekrar değerlendirebilirsiniz.

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(); 
    }); 
}); 

Güzel değil ama işe yarıyor.