2014-06-10 10 views
9

Bir siteye giriş yapmak için PhantomJS kullanıyorum. Sitede oturum açmak için OAuth kullanıldı. "Oturum Aç" düğmesine tıklamak sizi OAuth hizmetine götürür. Orada kimlik bilgilerinizi girip "Gönder" i tıkladığınızda, orijinal siteye yeniden yönlendirilirsiniz. Komutum iyi çalışıyor ancak çok sağlam görünmeyen zaman aşımlarına güveniyor.Sayfanın PhantomJS'de nasıl hazır olmasını bekleyebilirim?

Bu kodu, setTimeout kullanmak yerine sayfanın hazır olmasını beklemek için yeniden yazabilirim. Çoğu zaman, sayfanın hazır olmadığı ve jQuery'nin başlatılmadığı hatalarını görüyorum.

Javascript ile pek iyi değilim, bu yüzden bir örnek yardımcı olacaktır. Bir ton Googling'den sonra hacklediğim şey buydu.

var page = require('webpage').create(); 
var system = require('system'); 

page.settings.resourceTimeout = 10000; 
page.onResourceTimeout = function(e) { 
    console.log("Timed out loading resource " + e.url); 
}; 

page.open('https://mysite.com/login', function(status) { 
    if (status !== 'success') { 
     console.log('Error opening url'); 
     phantom.exit(1); 
    } else { 
     setTimeout(function() { 
      console.log('Successfully loaded page'); 
      page.evaluate(function() { 
       $("#submit-field").click(); //Clicking the login button 
      }); 

      console.log('Clicked login with OAuth button'); 
      setTimeout(function() { 
       console.log('Addding the credentials'); 
       page.evaluate(function() {     
        document.getElementById("username").value = '[email protected]'; 
        document.getElementById("password").value = '[email protected]'; 
        document.getElementById("Login").click(); 
       }); 
       console.log('Clicked login button'); 

       setTimeout(function() { 
        //Inject some jQuery into the page and invoke that here 
        console.log('Clicked the export button'); 
       }, 15000); 
      }, 15000); 
     }); 
    } 
}); 
+2

Doom dağından uzaklaşarak başlamanızı öneririm – fmsf

+2

Geçtiğimiz birkaç hafta boyunca bununla çalıştıktan sonra, şimdi bu "kıyamet dağı" ile ne kastettiğinizi biliyorum. Bu geri cehennem. –

cevap

14

Bunu yapmak için tek yol PhantomJS için DOM geri aramalar kullanmayı olduğunu görünüyor: İşte benim kod.

var page = require('webpage').create(); 
var system = require('system'); 

page.onInitialized = function() { 
    page.onCallback = function(data) { 
     console.log('Main page is loaded and ready'); 
     //Do whatever here 
    }; 

    page.evaluate(function() { 
     document.addEventListener('DOMContentLoaded', function() { 
      window.callPhantom(); 
     }, false); 
     console.log("Added listener to wait for page ready"); 
    }); 

}; 

page.open('https://www.google.com', function(status) {}); 
+0

webpage.create() işlevi, –

+0

@ HemantNagarkoti işleviyle ilgili bir işlev hatası değil. Web sayfasını npm aracılığıyla düğüm modülü olarak yüklediğinizden emin olun. npm web sayfasını yükle --save' – matt

1

için bir seçenek yöntem phantomjs waitfor.js example uzatmak olacaktır.

Bu kişisel yöntem yöntemini kullanıyorum. asenkron ama en

function waitFor(testFx, onReady, timeOutMillis) { 
    var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s 
     start = new Date().getTime(), 
     condition = false, 
     interval = setInterval(function() { 
      if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) { 
       // If not time-out yet and condition not yet fulfilled 
       condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code 
      } else { 
       if(!condition) { 
        // If condition still not fulfilled (timeout but condition is 'false') 
        console.log("'waitFor()' timeout"); 
        phantom.exit(1); 
       } else { 
        // Condition fulfilled (timeout and/or condition is 'true') 
        // console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms."); 
        typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condi> 
        clearInterval(interval); //< Stop this interval 
       } 
      } 
     }, 250); //< repeat check every 250ms 
} 

Bu yöntem değildir: (phantomjs waitfor.js example den waifFor() fonksiyonunun sadece kopyalayıp yapıştırmayın)

'use strict'; 

var wasSuccessful = phantom.injectJs('./lib/waitFor.js'); 
var page = require('webpage').create(); 

page.open('http://foo.com', function(status) { 
    if (status === 'success') { 
    page.includeJs('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js', function() { 
     waitFor(function() { 
     return page.evaluate(function() { 
      if ('complete' === document.readyState) { 
      return true; 
      } 

      return false; 
     }); 
     }, function() { 
     var fooText = page.evaluate(function() { 
      return $('#foo').text(); 
     }); 

     phantom.exit(); 
     }); 
    }); 
    } else { 
    console.log('error'); 
    phantom.exit(1); 
    } 
}); 

Ve lib/waitFor.js dosyası: Bu benim main.js dosyasıdır En azından bunları kullanmaya çalışmadan önce tüm kaynakların yüklendiğinden emin olabilirim.