如何从CasperJS访问iframe?

时间:2022-08-23 10:19:59

I have a webpage with an iframe. I'd like to access the contents of the iframe using CasperJS. In particular, I need to click buttons and fill a form. How can I do that?

我有一个带iframe的网页。我想使用CasperJS访问iframe的内容。特别是,我需要单击按钮并填写表单。我怎样才能做到这一点?

The main webpage is main.html:

主要网页是main.html:

<html><body>
<a id='main-a' href="javascript:console.log('pressed main-a');">main-a</a>
<iframe src="iframe.html"></iframe>
<a id='main-b' href="javascript:console.log('pressed main-b');">main-b</a>
</body></html>

The iframe is:

iframe是:

<html><body>
<a id='iframe-c' href="javascript:console.log('pressed iframe-c');">iframe-c</a>
</body></html>

My naïve approach:

我天真的做法:

var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() {
    this.click('a#main-a');
    this.click('a#main-b');
    this.click('a#iframe-c');
});

casper.run(function() {
    this.exit();
});

Doesn't work, of course, because the a#iframe-c selector isn't valid in the main frame:

当然,这不起作用,因为#iframe-c选择器在主框架中无效:

[info] [phantom] Starting...
[info] [phantom] Running suite: 2 steps
[debug] [phantom] opening url: http://jim.sh/~jim/tmp/casper/main.html, HTTP GET
[debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/main.html, type=Other, lock=true, isMainFrame=true
[debug] [phantom] url changed to "http://jim.sh/~jim/tmp/casper/main.html"
[debug] [phantom] Navigation requested: url=http://jim.sh/~jim/tmp/casper/iframe.html, type=Other, lock=true, isMainFrame=false
[debug] [phantom] Successfully injected Casper client-side utilities
[info] [phantom] Step 2/2 http://jim.sh/~jim/tmp/casper/main.html (HTTP 200)
[debug] [phantom] Mouse event 'click' on selector: a#main-a
[info] [remote] pressed main-a
[debug] [phantom] Mouse event 'click' on selector: a#main-b
[info] [remote] pressed main-b
[debug] [phantom] Mouse event 'click' on selector: a#iframe-c
FAIL CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c
#    type: uncaughtError
#    error: "CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c"
CasperError: Cannot dispatch click event on nonexistent selector: a#iframe-c    
  /tmp:901 in mouseEvent
  /tmp:365 in click
  /tmp/test.js:9
  /tmp:1103 in runStep
  /tmp:324 in checkStep

Is there any way to make this work? A hack that involves poking into phantomjs directly would be fine, but I don't know what to do there.

有没有办法让这项工作?涉及直接戳入phantomjs的黑客攻击会很好,但我不知道该怎么做。

I'm using CasperJS version 1.0.0-RC1 and phantomjs version 1.6.0.

我正在使用CasperJS版本1.0.0-RC1和phantomjs版本1.6.0。

5 个解决方案

#1


41  

Spent forever looking for this, and of course I found the answer minutes after posting the question.

花了很长时间寻找这个,当然我在发布问题后找到答案的几分钟。

I can use the new frame switching commands added to phantomjs in this commit. Specifically, the this.page.switchToChildFrame(0) and this.page.switchToParentFrame() functions. It appears undocumented, and it also seems that the methods have been changed for upcoming releases, but it does work:

我可以在此提交中使用添加到phantomjs的新帧切换命令。具体来说,this.page.switchToChildFrame(0)和this.page.switchToParentFrame()函数。它似乎没有文档,似乎已经为即将发布的版本更改了方法,但它确实有效:

var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() {
    this.click('a#main-a');
    this.click('a#main-b');
    this.page.switchToChildFrame(0);
    this.click('a#iframe-c');
    this.page.switchToParentFrame();
});

casper.run(function() {
    this.exit();
});

#2


35  

From 1.0 you can use withFrame

从1.0开始,您可以使用withFrame

  casper.open("http://www.example.com/page.html", function() {
    casper.withFrame('flashHolder', function() {
      this.test.assertSelectorExists('#the-flash-thing', 'Should show Flash');
    });
  });

#3


4  

As a matter of fact you'll have to use the new --web-security=no feature provided by Phantomjs 1.5 in order to be able to access those iFrames and their contents.

事实上,您必须使用Phantomjs 1.5提供的新的--web-security = no功能才能访问这些iFrame及其内容。

#4


3  

Suppose we have different frames(frame1 and frame2) and we have to access different elements(like click or check if div tag exits or not) of those frames.

假设我们有不同的帧(frame1和frame2),我们必须访问这些帧的不同元素(如点击或检查div标签是否退出)。

casper.withFrame('frame1', function() {
    var file = '//*[@id="profile_file"]';
    casper.thenClick(x(file));
});

casper.withFrame('frame2', function() {
  casper.then(function () {
     casper.waitForSelector('#pageDIV',
            function pass() {
                console.log("pass");
            },
            function fail(){
                console.log("fail");
            }
      );
   });
});

#5


0  

You can do something like this:

你可以这样做:

casper.start("url here...", function() { 
    this.withFrame(0, function() {
        this.evaluate(function() {
            document.querySelector('img#btn_start').click();
        })
    })
});

You can replace the zero with the name of the iframe.

您可以使用iframe的名称替换零。

#1


41  

Spent forever looking for this, and of course I found the answer minutes after posting the question.

花了很长时间寻找这个,当然我在发布问题后找到答案的几分钟。

I can use the new frame switching commands added to phantomjs in this commit. Specifically, the this.page.switchToChildFrame(0) and this.page.switchToParentFrame() functions. It appears undocumented, and it also seems that the methods have been changed for upcoming releases, but it does work:

我可以在此提交中使用添加到phantomjs的新帧切换命令。具体来说,this.page.switchToChildFrame(0)和this.page.switchToParentFrame()函数。它似乎没有文档,似乎已经为即将发布的版本更改了方法,但它确实有效:

var casper = require('casper').create({
    verbose: true,
    logLevel: "debug"
});

casper.start("http://jim.sh/~jim/tmp/casper/main.html", function() {
    this.click('a#main-a');
    this.click('a#main-b');
    this.page.switchToChildFrame(0);
    this.click('a#iframe-c');
    this.page.switchToParentFrame();
});

casper.run(function() {
    this.exit();
});

#2


35  

From 1.0 you can use withFrame

从1.0开始,您可以使用withFrame

  casper.open("http://www.example.com/page.html", function() {
    casper.withFrame('flashHolder', function() {
      this.test.assertSelectorExists('#the-flash-thing', 'Should show Flash');
    });
  });

#3


4  

As a matter of fact you'll have to use the new --web-security=no feature provided by Phantomjs 1.5 in order to be able to access those iFrames and their contents.

事实上,您必须使用Phantomjs 1.5提供的新的--web-security = no功能才能访问这些iFrame及其内容。

#4


3  

Suppose we have different frames(frame1 and frame2) and we have to access different elements(like click or check if div tag exits or not) of those frames.

假设我们有不同的帧(frame1和frame2),我们必须访问这些帧的不同元素(如点击或检查div标签是否退出)。

casper.withFrame('frame1', function() {
    var file = '//*[@id="profile_file"]';
    casper.thenClick(x(file));
});

casper.withFrame('frame2', function() {
  casper.then(function () {
     casper.waitForSelector('#pageDIV',
            function pass() {
                console.log("pass");
            },
            function fail(){
                console.log("fail");
            }
      );
   });
});

#5


0  

You can do something like this:

你可以这样做:

casper.start("url here...", function() { 
    this.withFrame(0, function() {
        this.evaluate(function() {
            document.querySelector('img#btn_start').click();
        })
    })
});

You can replace the zero with the name of the iframe.

您可以使用iframe的名称替换零。