Подтвердить что ты не робот

Как завершить PhantomJS script только после переадресации на стороне клиента

Я работаю над интегрированием браузера без заголовка PhantomJS в мой проект (в настоящее время использующий версию 1.6). По большей части, он отлично справляется с выполнением того, что мне нужно выполнить. Однако асинхронный характер того, как работают вызовы WebPage.open(), и необходимость вызова phantom.exit() в какой-то момент, затрудняет обработку переадресаций на стороне клиента, когда вы не можете предвидеть, собираюсь идти.

То, что мне нужно, это способ вызвать phantom.exit() только после того, как все мета обновится (что приведет к другой странице), и JavaScript-перенаправления, связанные с такими вещами, как onload-события, были выполнены. Я понимаю, почему это проблема, потому что теоретически переадресация на стороне клиента может проходить через какое-то количество секунд после загрузки страницы, и я не могу просто попросить возможность выйти только тогда, когда больше не будет перенаправлений, Прямо сейчас самое лучшее решение, о котором я могу думать, - это: a) вручную определить наличие элементов метаобновления на странице и разобраться с ними самостоятельно; b) использовать setInterval(), чтобы позволить некоторое разумное количество времени (например, 1- 1,5 секунды) до вызова phantom.exit(). В основном это будет выглядеть так:

var page = require('webpage').create();
var visitComplete = false;
var url = "http://some.url";
var pageOpenedTime;
setInterval(function() {
    if (visitcomplete && typeof pageOpenedTime != 'undefined' &&
        new Date() - pageOpenedTime >= 1500)
    {
        phantom.exit();
    }
), 1000);
page.open(url, function() {
    pageOpenedTime = new Date();
    if (!hasMetaRefresh(page)) {
        visitComplete = true;
    }
});

function hasMetaRefresh(page) {
    // Query the DOM here to detect meta refresh elements
}

Любые лучшие идеи?

Изменить: я должен упомянуть, что я впервые подумал, что может произойти событие PhantomJS, которое запускается, когда JavaScript, связанный с начальной загрузкой страницы, был выполнен, но обратный вызов onLoadFinished, как представляется, предшествует исполнению любой встроенной страницы JavaScript, включая события onload. Я также немного тестировал, сколько времени мне нужно подождать, и хотя 1000 мс достаточно долго для перенаправления JavaScript (через событие onload тела), чтобы выполнить выполнение на небольшой тестовой странице, 100 мс было недостаточно.

4b9b3361

Ответ 1

У меня была такая же проблема с загрузкой страницы, которая использовала Optimizely, а вариант был перенаправлен location.href.

Теперь я использую обратный вызов onNavigationRequest внутри функции "renderPage". Те оптимистически перенаправленные больше не блокируются, и мне не нужен произвольный тайм-аут.

var webpage = require('webpage');
var page = null;

var renderPage = function (myurl) {
    page = webpage.create();

    page.onNavigationRequested = function(url, type, willNavigate, main) {
        if (main && url!=myurl && url.replace(/\/$/,"")!=myurl&& (type=="Other" || type=="Undefined") ) {
        // main = navigation in main frame; type = not by click/submit etc

            log("\tfollowing "+myurl+" redirect to "+url)
            myurl = url;
            page.close();
            renderPage(url); // rerun this function wit the new URL
        }
    }; // on Nav req

    page.open(myurl, function(status) {
        if (status==="success") {
            page.render("screenshot.jpg");
        } else {
            page.close();
        }
    }); // page open
} // render page


renderPage("http://some.domain.com");

см. документы: http://phantomjs.org/api/webpage/handler/on-navigation-requested.html

Ответ 2

У меня есть идея использовать посмеянные таймеры для этой цели. Предположим, что мы включили "изделенный таймер" на странице. Таким образом, вы можете ускорить перемотку вперед, чтобы избежать времени простоя js. См. Примеры на странице GitHub.

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

Ответ 3

Я уже проверил различные примеры для обработки перенаправления phantomjs: тяжелая удача.

Пока нет универсального исправления. Если вы исправляете некоторые script как предложено здесь, он не удался в другом сценарии, например. помимо использования location.href, используя javascript для перенаправления. Я еще не тестировал тело. После того, как некоторые деньги заплатят здесь и там, я сдаюсь.

Я просто использую "тяжелый" Selenium, вызванный firefox, чтобы решить мои проблемы. Если вам нужно загрузить много страниц, вместо перезапуска firefox просто используйте webdriver.delete_all_cookies() для очистки некоторого улова. Это дает мне надежные результаты (мне нужно сделать захват экрана, загрузить html, получить окончательный url и многое другое) сравнить с phantomjs.