Как я могу подождать, пока страница будет готова в PhantomJS?

Я использую PhantomJS для входа на сайт и что-то делать. Сайт использовал OAuth для входа в систему. Нажав кнопку «Войти», перейдите в службу OAuth. Там вы вводите свои учетные данные и нажимаете «Отправить», вы перенаправляетесь обратно на исходный сайт. Мой скрипт отлично работает, но полагается на таймауты, которые не кажутся слишком надежными.

Как я могу переписать этот код, чтобы вместо использования setTimeoutя мог подождать, пока страница не будет готова. Я часто вижу ошибки, что страница не готова, поэтому jQuery не инициализируется.

Я не слишком хорош с Javascript, поэтому пример был бы полезен. Это то, что я взломал после тонны Гуглинга. Вот мой код:

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

javascript,phantomjs,

9

Ответов: 2


14 ов принято

Кажется, что единственный способ сделать это - использовать обратные вызовы из 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) {});

1

Альтернативным методом было бы расширение 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); } });

lib/waitFor.js

И waifFor()файл (который является всего лишь копией и waitfor.jsвставкой функции из waitfor.jsпримера phantomjs ):

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
}

Этот метод не является асинхронным, но, по крайней мере, я уверен, что все ресурсы были загружены до того, как я попытаюсь их использовать.

JavaScript, phantomjs,
Похожие вопросы