【问题标题】:Cannot get link to be clicked and switch to next page using PhantomJS无法使用 PhantomJS 获取要单击的链接并切换到下一页
【发布时间】:2016-08-02 01:51:54
【问题描述】:

我在让 phantomJS 单击网站上的登录按钮时遇到问题。

我可以在我的第二个屏幕截图中看到它正在尝试选择登录按钮,但我无法让它等待并在下一页截取屏幕截图。

这是我的 JS 文件:

var page = require('webpage').create();
page.viewportSize = {width: 1920,height: 1080};
page.open('http://clubs.bluesombrero.com/default.aspx?portalid=1809', function (status) {
    console.log("Status: " + status);
    if (status === "success") {
        var url = page.url;
        console.log('URL: ' + url);
        console.log("TC0001: Pass");
        page.render('TC0001.png');

        var a = page.evaluate(function() {
        return document.querySelector('#dnn_dnnLOGIN_cmdLogin');
        });

        page.sendEvent('click', a.offsetLeft, a.offsetTop);

        page.render('TC0002.png');
    } else {
        console.log("TC0001: Failed, Page did not load.");
    }
    phantom.exit();
});

我尝试了几种方法让它在页面加载后等待截屏,但我没有任何运气。

【问题讨论】:

    标签: javascript phantomjs


    【解决方案1】:

    page.sendEvent() 是一个同步函数,它会在其操作完成后立即结束。下一次调用 (page.render()) 甚至在点击触发的请求得到响应之前就已执行。

    1。 setTimeout

    JavaScript 提供了两个函数来等待静态时间:setTimeoutsetInterval

    page.sendEvent('click', a.offsetLeft, a.offsetTop);
    
    setTimeout(function(){
        page.render('TC0002.png');
        phantom.exit();
    }, 5000);
    

    (不要忘记删除另一个phantom.exit(),因为你不想过早退出)

    当然,现在的问题是,一方面页面可能在 5 秒后仍未准备好,或者另一方面页面加载速度非常快,只是坐在那里无所事事。

    2。 waitFor

    更好的方法是使用 PhantomJS 的示例文件夹中提供的waitFor() function。您可以等待页面的特定条件,例如特定元素的存在:

    page.sendEvent('click', a.offsetLeft, a.offsetTop);
    
    waitFor(function _testFx(){
        return page.evaluate(function(){
            return !!document.querySelector("#someID");
        });
    }, function _done(){
        page.render('TC0002.png');
        phantom.exit();
    }, 10000);
    

    3。 page.onLoadFinished

    另一种方法是监听page.onLoadFinished 事件,该事件将在下一页加载时调用,但您应该在单击之前注册它:

    page.onLoadFinished = function(){
        page.render('TC0002.png');
        phantom.exit();
    };
    
    page.sendEvent('click', a.offsetLeft, a.offsetTop);
    

    4。 page.onPageCreated

    每当在桌面浏览器中打开新窗口/选项卡时,page.onPageCreated 都会在 PhantomJS 中触发。它提供了对新创建页面的引用,因为之前的页面没有被覆盖。

    page.onPageCreated = function(newPage){
        newPage.render('TC0002.png');
        newPage.close();
    
        phantom.exit();
    };
    
    page.sendEvent('click', a.offsetLeft, a.offsetTop);
    

    在所有其他情况下,page 实例被新页面覆盖。

    5。 “完整”页面加载

    这可能还不够,因为 PhantomJS 没有指定页面加载时的含义,并且页面的 JavaScript 可能仍会发出进一步的请求来构建页面。此问答提供了一些等待“完整”页面加载的好建议:phantomjs not waiting for “full” page load

    【讨论】:

    • page.onLoad 大部分时间都完成了工作。但在较长的页面加载上,它似乎继续不成熟。使用 waitFor 和 setTimeout/setInterval 我的代码似乎运行了多次。我似乎无法弄清楚为什么
    • 您可以将超时设置为某个天文值或更改waitFor 的实现而不忽略超时。像这样的东西:function indefiniteWait(check, done) { setTimeout(function(){ if(check()) done() }, 250) }。就是这样。
    • 在节点中使用幻像作为子进程时如何实现这一点?
    • @Carl91 如果您使用 PhantomJS 作为子进程,那么我的回答适用于 100%。请更具体地说明您的问题是什么。我建议你问一个新问题。
    • 我序列号。事实上,我做到了:) ucan 喜欢这里stackoverflow.com/questions/42861422/…
    猜你喜欢
    • 1970-01-01
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多