2014-06-10 13 views
9

Tôi đang sử dụng PhantomJS để đăng nhập vào một trang web để làm điều gì đó. Trang web đã sử dụng OAuth để đăng nhập. Nhấp vào nút "Đăng nhập" trên trang, sẽ đưa bạn đến dịch vụ OAuth. Ở đó bạn nhập thông tin đăng nhập của bạn và nhấp vào "Gửi", bạn sẽ được chuyển hướng trở lại trang web gốc. Kịch bản của tôi hoạt động tốt nhưng dựa trên thời gian chờ mà dường như không quá mạnh.Làm cách nào để đợi trang sẵn sàng trong PhantomJS?

Làm cách nào tôi có thể viết lại mã này để thay vì sử dụng setTimeout, tôi có thể đợi cho đến khi trang sẵn sàng. Tôi thường thấy lỗi rằng trang không sẵn sàng và do đó jQuery không được khởi tạo.

Tôi không quá tốt với Javascript nên một ví dụ sẽ hữu ích. Đây là những gì tôi đã hack với nhau sau một tấn Googling. Đây là mã của tôi:

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

Tôi khuyên bạn nên bắt đầu bằng cách di chuyển ra khỏi núi doom – fmsf

+2

Sau khi làm việc với điều này trong vài tuần qua, bây giờ tôi biết ý bạn là gì "núi doom" này. Đó là địa ngục gọi lại. –

Trả lời

14

Có vẻ như cách duy nhất để làm điều này là sử dụng gọi lại từ DOM đến PhantomJS.

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() không phải là lỗi chức năng nhận được –

+0

@HemantNagarkoti Đảm bảo bạn cài đặt trang web làm mô-đun nút qua npm. Trang web 'npm install --save' – matt

1

Một phương pháp thay thế sẽ được mở rộng phantomjs waitfor.js example.

Tôi sử dụng phương thức kết hợp này của cá nhân. Đây là main.js tập tin của tôi:

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

lib/waitFor.js tập tin (mà chỉ là một sao chép và dán các waifFor() chức năng từ phantomjs waitfor.js example):

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 
} 

Phương pháp này không đồng bộ nhưng ở ít nhất tôi chắc chắn rằng tất cả các nguồn lực đã được nạp trước khi tôi thử sử dụng chúng.

Các vấn đề liên quan