为什么简单的JavaScript在CasperJS中不起作用?

时间:2013-08-20 06:30:36

标签: javascript casperjs

我是CasperJS的新手。 this.echo(this.getTitle());如何运作,但console.log("Page Title ", document.title);没有?另外为什么我的document.querySelector不工作?有没有人有一个很好的解释?我可以在CasperJS文档中找到答案吗?

这是我的代码:

var casper = require('casper').create();
var url = 'http://www.example.com/';

 casper.start(url, function() {
     this.echo(this.getTitle()); // works
     this.echo(this.getCurrentUrl()); // works
});

casper.then(function(){
    this.echo(this.getCurrentUrl()); // works
    console.log("this is URL: ", document.URL); // doesn't work
    console.log("Page Title ", document.title); // doesn't work
    var paragraph = document.querySelectorAll('p')[0].innerHTML;
    console.log(paragraph); // doesn't work
});

casper.run();

修改 我现在正在使用casper.thenEvaluate和casper.evaluate,它仍然无法正常工作。有什么想法吗?

var casper = require('casper').create();
var url = 'http://www.example.com/';

casper.start(url, function() {
    this.echo(this.getTitle()); // works
    this.echo(this.getCurrentUrl()); // works
    console.log('page loaded: '); // works
});

casper.thenEvaluate(function(){
    var paragraph = document.querySelectorAll('p')[0].innerHTML; // doesn't work
    console.log(paragraph); // doesn't work
    console.log("Page Title ", document.title); // doesn't work
});

casper.run();

4 个答案:

答案 0 :(得分:7)

您必须使用document调用依赖this.evaluate的函数:

var paragraph = this.evaluate(function() {
    return document.querySelector('p').innerHtml;
});

如有疑问,请咨询the docs

答案 1 :(得分:3)

CasperJS继承了DOM上下文(页面上下文)与PhantomJS外部上下文之间的分离。您只能通过casper.evaluate()访问沙盒DOM上下文。 document回调中的evaluate()是您在普通JavaScript中所期望的变量,但在document之外还有一个evaluate(),它只是一个虚拟对象而且不是#39; t提供对页面DOM的访问。

如果要访问DOM属性,则需要使用evaluate()

var title = casper.evaluate(function(){
    return document.title;
});

但是这对DOM节点不起作用,因为只有原始对象可以传递出DOM上下文。 PhantomJS文档说明如下:

  

注意: evaluate函数的参数和返回值必须是一个简单的原始对象。经验法则:如果它可以通过JSON序列化,那就没关系了。

     

闭包,函数,DOM节点等将工作!

如果你想使用document.querySelector(),那么你需要生成一个可以传递到外面的DOM节点的表示

var form = casper.evaluate(function() {
    var f = document.querySelector('form');
    return { html: f.innerHTML, action: f.action };
});
casper.echo(JSON.stringify(form, undefined, 4));

您还可以使用所有可用的CasperJS函数来提供DOM节点的表示,例如casper.getElementsInfo()

另外,请查看Understanding the evaluate function in CasperJS

答案 2 :(得分:0)

this.getTitle()在Casper对象上执行getTitle()函数并在Casper上下文中运行,因此它会产生预期的结果。

但是,“文档”在Casper上下文中不可用。根本原因是Casper正在运行PhantomJS,这是一个Web浏览器。因此,'document'仅在浏览器中可用,它比Casper上下文中运行的代码“更深”。在两个环境之间没有直接的共享变量的方法,但有一种方法可以通过复制值将它们作为参数传递。

两个环境(Casper和Phantom)之间的“桥梁”是Casper的“评估”功能。函数内部的所有内容(作为参数传递给'evaluate')都将在浏览器上下文中执行,而不是在Casper上下文中执行。这是一个重要的区别。如Blender所述,此处提供了文档:

http://docs.casperjs.org/en/latest/modules/casper.html#evaluate

以下示例:

 casper.evaluate(function(username, password) {
     document.querySelector('#username').value = username;
     document.querySelector('#password').value = password;
     document.querySelector('#submit').click(); 
 }, 'sheldon.cooper', 'b4z1ng4');

在给定的示例中,您可以看到如何将“用户名”和“密码”参数从Casper环境传递到浏览器(页面)环境。

匿名“功能(用户名,密码)”将在浏览器中执行。因此,您可以在其中使用“文档”。

您也可以将值传回,可以在Casper端获取。即

var result = casper.evaluate(function run_in_browser(){
    return document.title;
});

答案 3 :(得分:0)

尝试this.echo(this.fetchText('p'));获取innerhtml。 Refer documentation