简体   繁体   English

我怎样才能在PhantomJS中等待页面准备好?

[英]How can I wait for the page to be ready in PhantomJS?

I'm using PhantomJS to log into a site an do something. 我正在使用PhantomJS登录网站做某事。 The site used OAuth for logging in. Clicking on the "Login" button on the, takes you to the OAuth service. 该网站使用OAuth进行登录。点击该按钮上的“登录”按钮,即可转到OAuth服务。 There you enter your credentials and clicking "Submit", you get redirected back to the original site. 在那里输入您的凭据并单击“提交”,您将被重定向回原始站点。 My script works fine but relies on timeouts which doesn't seem too robust. 我的脚本工作正常,但依赖于看似不太强大的超时。

How can I rewrite this code so that instead of using setTimeout , I can wait until the page is ready. 我怎样才能重写这段代码,这样我就可以等到页面准备好了,而不是使用setTimeout I often see errors that the page isnt' ready and therefore jQuery isn't initialized. 我经常看到页面没有准备好的错误,因此jQuery没有初始化。

I'm not too good with Javascript so an example would be helpful. 我对Javascript不是很好,所以一个例子会有所帮助。 This is what I've hacked together after a ton of Googling. 这是我经过大量谷歌搜索后一起攻击的内容。 Here's my code: 这是我的代码:

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 = 'user@example.com';
                    document.getElementById("password").value = 'P@ssw0rd';
                    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);
        });
    }
});

It seems that the only way to do this was to use callbacks from the DOM to PhantomJS. 似乎这样做的唯一方法是使用从DOM到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) {});

An alternate method would be to extend the phantomjs waitfor.js example . 另一种方法是扩展phantomjs waitfor.js示例

I use this personnal blend of method. 我用这种人的方法混合。 This is my main.js file: 这是我的main.js文件:

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

And the lib/waitFor.js file (which is just a copy and paste of the waifFor() function from the phantomjs waitfor.js example ): lib/waitFor.js文件(它只是phantomjs waitfor.js示例中 waifFor()函数的复制和粘贴):

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
}

This method is not asynchronous but at least am I assured that all the resources were loaded before I try using them. 这个方法不是异步的,但至少我确信在尝试使用它们之前已经加载了所有资源。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM