简体   繁体   English

为什么普通的JavaScript在CasperJS中不起作用?

[英]Why doesn't plain JavaScript work in CasperJS?

I'm new to CasperJS. 我是CasperJS的新手。 How come this.echo(this.getTitle()); this.echo(this.getTitle()); works but console.log("Page Title ", document.title); 可以,但是console.log("Page Title ", document.title); doesn't? 不是吗 Also why isn't my document.querySelector working? 另外,为什么我的document.querySelector无法正常工作? Does anyone have a good explanation? 有人有很好的解释吗? Where in the CasperJS documentation can I find the answer? 在CasperJS文档中哪里可以找到答案?

Here's my code: 这是我的代码:

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();

EDIT: I'm using casper.thenEvaluate and casper.evaluate now and it's still not working. 编辑:我现在使用casper.thenEvaluate和casper.evaluate,它仍然无法正常工作。 Any ideas? 有任何想法吗?

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();

You have to call functions that depend on document with this.evaluate : 您必须使用this.evaluate调用依赖于documentthis.evaluate

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

When in doubt, consult the docs . 如有疑问,请查阅文档

CasperJS has inherited the split between DOM context (page context) and the outer context from PhantomJS. CasperJS从PhantomJS继承了DOM上下文(页面上下文)和外部上下文之间的分隔。 You can only access the sandboxed DOM context through casper.evaluate() . 您只能通过casper.evaluate()访问沙盒DOM上下文。 document inside of the evaluate() callback is the variable that you would expect in normal JavaScript, but there is also a document outside of evaluate() which is only a dummy object and doesn't provide access to the DOM of the page. evaluate()回调内部的document是您在普通JavaScript中所期望的变量,但evaluate()外部还有一个document ,它只是一个虚拟对象,不提供对页面DOM的访问。

If you want to access DOM properties, then you need to use evaluate() . 如果要访问DOM属性,则需要使用evaluate()

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

But this won't work for DOM nodes, because only primitive objects can be passed out of the DOM context. 但这不适用于DOM节点,因为只能将原始对象传递出DOM上下文。 The PhantomJS documentation says the following: PhantomJS文档说明以下内容:

Note: The arguments and the return value to the evaluate function must be a simple primitive object. 注意:参数和evaluate函数的返回值必须是一个简单的原始对象。 The rule of thumb: if it can be serialized via JSON, then it is fine. 经验法则:如果可以通过JSON序列化,那就很好。

Closures, functions, DOM nodes, etc. will not work! 闭包功能,DOM节点等等都不行!

If you want to use document.querySelector() , then you need to produce a representation of a DOM node that can be passed outside: 如果你想使用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));

You can also use all of the available CasperJS functions that can provide representations of DOM nodes such as casper.getElementsInfo() . 您还可以使用所有可用的CasperJS函数,这些函数可以提供DOM节点的表示形式,例如casper.getElementsInfo()

Also, have a look at Understanding the evaluate function in CasperJS . 另外,看看了解CasperJS中的评估函数

this.getTitle() executes getTitle() function on Casper object and runs in Casper context, hence it produces the expected result. this.getTitle()在Casper对象上执行getTitle()函数并在Casper上下文中运行,因此会产生预期的结果。

However, 'document' is not available in Casper context. 但是,“文档”在Casper上下文中不可用。 The underlying reason is that Casper is running PhantomJS, which is a web browser. 根本原因是Casper正在运行Web浏览器PhantomJS。 So, 'document' is only available in the browser, which is one level "deeper" than the code that runs in Casper context. 因此,“文档”仅在浏览器中可用,该浏览器比在Casper上下文中运行的代码“更深”一层。 There is no direct way to share variables between the two environments but there is a way to pass them as parameters by copying the value. 没有直接的方法可以在两个环境之间共享变量,但是可以通过复制值将它们作为参数传递。

The "bridge" between the two environments (Casper and Phantom) is Casper's 'evaluate' function. 两种环境(Casper和Phantom)之间的“桥梁”是Casper的“评估”功能。 Everything inside the function, passed to 'evaluate' as a parameter, will get executed in the browser context, not in Casper context. 函数内部传递给参数“ evaluate”的所有内容都将在浏览器上下文中执行,而不是在Casper上下文中执行。 That's an important distinction. 这是一个重要的区别。 The documentation is available here, as noted by Blender: 如Blender所述,此处提供了文档:

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

Example below: 下面的例子:

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

In the given example you can see how to pass "username" and "password" parameters from Casper environment to the browser (page) environment. 在给定的示例中,您可以看到如何将Casper环境中的“用户名”和“密码”参数传递给浏览器(页面)环境。

The anonymous "function(username,password)" will get executed within the browser. 匿名“函数(用户名,密码)”将在浏览器中执行。 Therefore, you can use 'document' inside it. 因此,您可以在其中使用“文档”。

You can also pass the value back, which can be picked up on Casper side. 您还可以将值传递回去,该值可以在Casper一侧获取。 Ie

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

Try this.echo(this.fetchText('p')); 试试this.echo(this.fetchText('p')); to get innerhtml. 获得innerhtml。 Refer documentation 参考文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM