21

我正在将 PhantomJS 无头浏览器集成到我的一个项目中(目前使用 1.6 版)。在大多数情况下,它在完成我需要完成的工作方面做得很好。但是,WebPage.open() 调用工作方式的异步性质,以及在某些时候调用 phantom.exit() 的需要,使得当您无法预测客户端重定向的去向时处理客户端重定向变得很棘手去。

我所追求的是一种仅在任何元刷新(导致不同页面)和与 onload 事件等相关的 JavaScript 重定向执行后调用 phantom.exit() 的方法。我知道为什么这是一个问题,因为理论上客户端重定向可以在页面加载后的任意秒数发生,我不能简单地要求只有在不再发生重定向才能退出. 现在,我能想到的最好的解决方案是 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
}

有更好的想法吗?

编辑:我应该提到我的第一个想法是,当执行与初始页面加载相关的 JavaScript 时,可能会触发一个 PhantomJS 事件,但 onLoadFinished 回调似乎先于任何页内 JavaScript 的执行,包括加载事件。我还测试了我可能需要等待多少时间间隔,虽然 1000 毫秒足以让 JavaScript 重定向(通过 body onload 事件)在一个小测试页面中执行,但 100 毫秒还不够长。

4

3 回答 3

8

我在加载使用 Optimizely 的页面时遇到了同样的问题,并且变体是 location.href 重定向。

我现在在“renderPage”函数中使用 onNavigationRequest 回调。那些优化重定向不再阻塞,我不需要任意超时。

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

于 2013-06-29T20:03:44.187 回答
0

我有想法为此目的使用模拟计时器。假设我们在页面中包含“模拟计时器”。这样,您可以快进时间以避免 js 空闲时间。请参阅 GitHub 页面上的示例。

这只是一种使事情发生得更快的方法,但正如您所料,无法确定将来是否会触发重定向事件。

于 2013-05-10T08:58:59.700 回答
0

我已经检查了 phantomjs 重定向处理的各种示例:运气不好。

目前,还没有通用的解决方法。如果你 按照这里的建议修补一些脚本,它会在其他情况下失败,例如除了使用 location.href,使用 javascript 重定向。我还没有测试身体。在到处打了几块钱后,我放弃了。

我只是使用“重”硒触发的火狐来解决我的问题。如果你需要加载很多页面,而不是重新启动firefox,只需使用webdriver.delete_all_cookies()清理一些catch。与 phantomjs 相比,它给了我可靠的结果(我需要进行屏幕截图、下载 html、获取最终 url 等等)。

于 2016-09-07T17:25:14.860 回答