如何在 PhantomJS 中捕获 window.open(url, _blank) 打开的新窗口?

2024-01-21

我想用 PhantomJS 检查我的脚本是否在单击时正确打开新窗口/选项卡。 open是由js事件监听触发并通过window.open(url, "_blank").

如何使用 PhantomJS 监听新窗口?


似乎有三种方法可以做到这一点:

页面创建时

CasperJS 通过使用解决了这个问题page.onPageCreated http://phantomjs.org/api/webpage/handler/on-page-created.html。所以当window.open在页面中调用,创建一个新页面并page.onPageCreated由新创建的页面触发。

page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        page.onPageCreated = function(newPage){
            newPage.onLoadFinished = function(){
                console.log(newPage.url);
                phantom.exit();
            };
        };
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})

pages

PhantomJS'page has a pages http://phantomjs.org/api/webpage/property/pages.html处理子页面的属性。所以,当你open一个新的页面/标签,一个新的webpage为该页面创建对象。您需要尝试添加一个onLoadFinished在页面触发之前监听页面的事件(没有承诺)。这可能很困难,当window.open从页面上下文中以未知的延迟调用。

这可以通过使用类似的东西来解决waitFor https://github.com/ariya/phantomjs/blob/master/examples/waitfor.js等待新页面出现并在加载页面之前附加事件处理程序。这是经过小调整的完整代码。重试间隔从 250ms 减少到 50ms。

var page = require('webpage').create();
var address = "http://example.com/";

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 condition is fulfilled
                    clearInterval(interval); //< Stop this interval
                }
            }
        }, 50); //< repeat check every 50ms
};

page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        console.log("p:", page.ownsPages, typeof page.pages, page.pages.length, page.pages);
        waitFor(function test(){
            return page.pages && page.pages[0];
        }, function ready(){
            page.pages[0].onLoadFinished = function(){
                console.log("p:", page.ownsPages, typeof page.pages, page.pages.length, page.pages);
                console.log("inner:", page.pages[0].url);
                phantom.exit();
            };
        });
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})

代理解决方案

The window.open函数可以被代理,并且在页面上下文中打开页面后,可以在幻像上下文中注册事件处理程序,并通过以下方式发出信号window.callPhantom并陷入onCallback http://phantomjs.org/api/webpage/handler/on-callback.html.

page.onInitialized = function(){
    page.evaluate(function(){
        var _oldOpen = window.open;
        window.open = function(url, type){
            _oldOpen.call(window, url, type);
            window.callPhantom({type: "open"});
        };
    });
};
page.onCallback = function(data){
    // a little delay might be necessary
    if (data.type === "open" && page.pages.length > 0) {
        var newPage = page.pages[page.pages.length-1];
        newPage.onLoadFinished = function(){
            console.log(newPage.url);
            phantom.exit();
        };
    }
};
page.open(address, function (status) {
    if (status !== 'success') {
        console.log('Unable to load the address!');
        phantom.exit();
    } else {
        page.evaluate(function(url){
            window.open(url+"?something=other", "_blank");
        }, address);
    }
})
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 PhantomJS 中捕获 window.open(url, _blank) 打开的新窗口? 的相关文章

随机推荐

  • 使用 API 以编程方式在 Azure DevOps Pipeline 中添加和更新测试

    我正在将我们的一个项目转换为使用 Azure DevOps 而不是 AppVeyor 进行 CI 作为构建的一部分 我们使用自定义测试运行器来执行某些测试 在 AppVeyor 中运行时 我们直接从测试运行程序调用 REST API 以通知
  • BroadcastReceiver 尝试在无序广播期间返回结果 - SMS Receiver

    我知道有很多这样的帖子 但没有一个对我有帮助 我的清单声明
  • java中的速率控制

    我正在寻找一个好的解决方案或者可能是一个 API 来解决以下问题 我的应用程序循环执行一项任务 例如发送电子邮件等 我需要将消息的平均速率限制为例如每秒 100 条消息或每最后一分钟 1000 条消息 不 我正在寻找一种算法或 API 来完
  • 如何在 Ansible 中更改和使用每个主机的全局变量?

    我正在尝试编写一个剧本来设置具有多个从服务器的 mysql 主从复制 对于每个从属服务器 我需要访问一个名为 next id 的变量 该变量应该在用于每个主机之前递增 例如 对于第一个从服务器 next id 应为 2 对于第二个从服务器
  • 批量http请求

    有谁知道批量http请求的标准方法 含义 在一次往返中发送多个 http 原子请求 出于性能原因 我们在 REST API 实现中需要这样的机制 这种机制可以显着减少客户端使用 API 所需执行的往返次数 提前致谢 Shay 定义包含客户端
  • 这个图案的名字? (答案:带有双重检查锁定的延迟初始化)

    考虑以下代码 public class Foo private static object lock new object public void NameDoesNotMatter if SomeDataDoesNotExist lock
  • 为什么这个全局变量没有被改变?

    为什么会出现 null 而不是设置为 ajax 调用返回的数据 我忽略的一定是一些简单的事情 var message document ready function fbFetchMessage alert message function
  • 如何从基于 Django 的站点管理任务的停止或重新启动?

    我将在服务器中运行一个脚本 该脚本将自动在数据库中创建模型实例 这个想法是使用无限循环 例如 while True 它将无休止地创建实例 直到我以某种方式停止它 我想使用 Django 从我的网站上很好地检查我的数据库有多大 然后我想停止或
  • DIV 重叠粘性页脚

    我有一个包含其他三个 div 的 div 页眉 内容 页脚 div class note div class header Title div div class content Some content div div class foo
  • fread (data.table) 选择列,如果未找到列则抛出错误

    我正在使用 data tables 将 csv 文件加载到 R 中fread功能 它有一堆我不需要的列 所以select参数就派上用场了 但是 我注意到 如果 csv 文件中不存在 select 中指定的列之一 则 fread 将默默地继续
  • 重新运行时将 Unicode 参数传递给 Windows .bat 文件

    我的 bat 文件如下所示 echo off CD D dp0 if 2 set user USERNAME else set user 2 getFile if 1 set p file Enter file name else set
  • 获取直到特定字符的字符串

    var hello hello how are you var hello2 hello how are you tom 我想删除 符号后面的每个字母 结果应该是 var hello2 hello how are you tom gt he
  • Postman Collection Run 确实会因 setTimeout 调用而暂停

    我在请求的测试部分放置了一个简单的 setTimeout function 10000 调用 当我单独运行该步骤时效果很好 当我执行 Collection Run 时 该步骤就会被执行 并且 Postman 会继续前进而不会暂停 这是设计使
  • HTML5 画布图像在 Chrome 中不可见

    我正在使用 HTML5 画布并在那里放置两个图像 但我面临一个问题 即一个图像已加载并在 chrome 中可见 但另一个图像仅在 mozilla 中可见 但在刷新后 我不知道为什么会发生这种情况 因为我是画布新手 var canvas do
  • 为什么这个外键约束的形成不正确?

    我是如何得出这个问题的 其本身就是一堆错误消息 首先 这是错误消息1452 Cannot add or update a child row a foreign key constraint fails 尝试使用绝对有效的外键插入数据 现在
  • 如何更改 Mediawiki 1.19.1 的登陆页面以直接转到 Special:UserLogin

    我正在尝试设置一个私有 Mediawiki 实例 它希望用户登录才能查看任何内容 我尝试调整 Localsettings php 文件中的 wgWhitelistRead 变量 但它仍然将我带到一个显示 需要登录 的页面 如果用户未登录 我
  • 获取ADO.NET中的输出参数值

    我的存储过程有一个输出参数 ID INT OUT 我如何使用 ado net 检索此内容 using SqlConnection conn new SqlConnection SqlCommand cmd new SqlCommand sp
  • 如果路径中有空格则 ShellExecute 失败

    我有一个 Delphi 应用程序 它使用 ShellExecute 在按下按钮时调用第二个 Delphi 应用程序 应用程序存储在同一服务器上的同一网络共享上 它们的路径格式如下 const JobManager Z Apps Applic
  • Python OpenCV cv2 绘制带有文本的矩形

    我使用在图像上绘制一个矩形 cv2 rectangle frame x y x1 y1 0 255 0 2 我想绘制带有文本信息的矩形 我该怎么做 有可用的现成可用的实现吗 或者我应该匹配矩形的左上角坐标并尝试使用 cv2 矩形元素显示不同
  • 如何在 PhantomJS 中捕获 window.open(url, _blank) 打开的新窗口?

    我想用 PhantomJS 检查我的脚本是否在单击时正确打开新窗口 选项卡 open是由js事件监听触发并通过window open url blank 如何使用 PhantomJS 监听新窗口 似乎有三种方法可以做到这一点 页面创建时 C