javascript - 使用 casperjs 通过一级 iframe 对嵌套链接进行分组

标签 javascript iframe casperjs

我有以下代码:

var casper = require("casper").create({
        //  verbose: true,
        //    logLevel: "debug",
        webSecurityEnabled : false
    });
var links = [];
function get_links(obj) {
    return obj.evaluate(function () {
        var i,
            l = document.querySelectorAll("a"),
            l2 = [];
        for (i = 0; i < l.length; i++) {
            l2[i] = l[i].href;
        }
        return l2
    });
}
function unique(arr) {
    var obj = {};
    for (var i = 0; i < arr.length; i++) {
        if (/http(.*)?/.test(arr[i])) {
            var str = arr[i];
            obj[str] = true;
        }
    }
    return Object.keys(obj);
}

function getLinksFromIframes(callback) {
    this.echo("Here we come: " + this.getCurrentUrl() + "\n");
    function to_frame(obj) {
        var iframes = to_evaluate(obj);
        iframes.forEach(function (index) {
            this.withFrame(index, function () {
                this.echo("We are here: " + this.getCurrentUrl());
                var l = unique(get_links(this));
                var i;
                for (i = 0; i < l.length; i++) {
                    console.log(l[i]);
                    links.push(l[i])
                }
                links = unique(links);
                console.log("");
                to_frame(this)
            });
        }, obj);
    }
    function to_evaluate(obj) {
        return obj.evaluate(function () {
            var iframes = [];
            [].forEach.call(document.querySelectorAll("iframe"), function (iframe, i) {
                iframes.push(i);
            });
            return iframes;
        })
    }
    to_frame(this);
    this.then(function () {
        callback.call(this);
    });
}

casper.start("http://domu-test-2/node/1", function () {
    getLinksFromIframes.call(this, function () {
        console.log("Done!\n");
        var i;
        for (i = 0; i < links.length; i++) {
            console.log(links[i]);
        }
    });
}).then(function () {}).run();

现在的问题是:

如果想通过一级iframe获取链接,应该如何重构getLinksFromIframes()函数。目前他们共享一个“全局”变量links。我认为 links 肯定会是链接列表的列表,并在 withFrame 函数中初始化新列表,然后将这个新引用传递给子 iframe。那么我应该如何传递它并“回溯”嵌套 iframe 中的所有链接?

最佳答案

如果我没看错,您希望选择从哪个 iframe 获取链接并且仅从该 iframe 获取链接。如果是这种情况,那么您可以简单地使用 switchToChildFrame 切换到所需的 iframe,然后通过调用 get_links(obj) 获取链接。

我的示例有 3 页。在 iframe 中加载 iframe1.htmlindex.htmliframe1.html 中有另一个加载 iframe2.html< 的 iframe/。每个文件内部有 3 个链接:

index.html

<a href="link1/from/index">Link 1 from index</a>
<a href="link2/from/index">Link 2 from index</a>
<a href="link3/from/index">Link 3 from index</a>

<iframe src="iframe1.html"></iframe>

iframe1.html

<a href="link1/from/iframe1">Link 1 from iframe 1</a>
<a href="link2/from/iframe1">Link 2 from iframe 1</a>
<a href="link3/from/iframe1">Link 3 from iframe 1</a>

<iframe src="iframe2.html"></iframe>

iframe2.html

<a href="link1/from/iframe2">Link 1 from iframe 2</a>
<a href="link2/from/iframe2">Link 2 from iframe 2</a>
<a href="link3/from/iframe2">Link 3 from iframe 2</a>

重构后的 getLinksFromIframes 函数将如下所示:

function getLinksFromIframes(callback) {
    this.echo("Here we come: " + this.getCurrentUrl() + "\n");

    function to_frame(obj) {
        obj.echo("We are here: " + obj.getCurrentUrl());
        var l = unique(get_links(obj));
        var i;
        for (i = 0; i < l.length; i++) {
            console.log(l[i]);
            links.push(l[i])
        }
        links = unique(links);
        console.log("");
    }
    function to_evaluate(obj) {
        return obj.evaluate(function () {
            var iframes = [];
            [].forEach.call(document.querySelectorAll("iframe"), function (iframe, i) {
                iframes.push(i);
            });
            return iframes;
        })
    }

    // Leave both switchToChildFrame as comments to get the "index.html" links
    this.page.switchToChildFrame(0); // Uncomment to get the links of "iframe1.html"
    //this.page.switchToChildFrame(0); // Uncomment to get the links of "iframe2.html"
    to_frame(this);

    this.then(function () {
        callback.call(this);
    });
}

结果

如果您同时评论 switchToChildFrame,您将获得 index.html 的链接:

casperjs caspers-read-iframes.js
Here we come: http://pjs.lytrax.net/node/1/

We are here: http://pjs.lytrax.net/node/1/
http://pjs.lytrax.net/node/1/link1/from/index
http://pjs.lytrax.net/node/1/link2/from/index
http://pjs.lytrax.net/node/1/link3/from/index

Done!

http://pjs.lytrax.net/node/1/link1/from/index
http://pjs.lytrax.net/node/1/link2/from/index
http://pjs.lytrax.net/node/1/link3/from/index

如果您取消注释第一个 switchToChildFrame,您将获得第一级 iframe1.html 的链接:

casperjs caspers-read-iframes.js
Here we come: http://pjs.lytrax.net/node/1/

We are here: http://pjs.lytrax.net/node/1/iframe1.html
http://pjs.lytrax.net/node/1/link1/from/iframe1
http://pjs.lytrax.net/node/1/link2/from/iframe1
http://pjs.lytrax.net/node/1/link3/from/iframe1

Done!

http://pjs.lytrax.net/node/1/link1/from/iframe1
http://pjs.lytrax.net/node/1/link2/from/iframe1
http://pjs.lytrax.net/node/1/link3/from/iframe1

如果您取消注释第一个和第二个 switchToChildFrame,您将获得第二级 iframe2.html 的链接:

casperjs caspers-read-iframes.js
Here we come: http://pjs.lytrax.net/node/1/

We are here: http://pjs.lytrax.net/node/1/iframe2.html
http://pjs.lytrax.net/node/1/link1/from/iframe2
http://pjs.lytrax.net/node/1/link2/from/iframe2
http://pjs.lytrax.net/node/1/link3/from/iframe2

Done!

http://pjs.lytrax.net/node/1/link1/from/iframe2
http://pjs.lytrax.net/node/1/link2/from/iframe2
http://pjs.lytrax.net/node/1/link3/from/iframe2

关于javascript - 使用 casperjs 通过一级 iframe 对嵌套链接进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41080042/

相关文章:

javascript - CasperJS 在使用 sendKeys 时不上传文件

javascript - 我一直在尝试通过用户输入使用 for 循环,但由于某种原因它既不显示错误也不显示输出

javascript - 使用 Webpack 动态导入命名导出

javascript - 在 iFrame 中运行自定义 JavaScript 代码的问题

javascript - CasperJS 选择具有指定文本的复选框

javascript - 如何使用casperjs点击一个随机链接并导航到另一个页面?

JavaScript 内联函数到数组映射

javascript - 无法删除 Canvas 中的图像: javascript

javascript - 使用 javascript 更改 iframe 的 src

javascript - 使用 JS 如何阻止子 Iframe 重定向或至少提示用户重定向