官网http://casperjs.org/
分享http://download.csdn.net/detail/xiarendeniao/5781445
环境:
[dongsong@localhost ~]$ casperjs --version
1.0.0-RC2
[dongsong@localhost ~]$ phantomjs --version
1.7.0
提交表单可以通过fill直接完成(有些提交是js控制的,这种方法就行不通了)或者用click()点击提交按钮
下面给一个在evaluate内部做的例子(跟普通页面上的js编程类似)
// Querying for "Chuck Norris" on Google
casper.start('http://google.fr/').thenEvaluate(function(term) {
document.querySelector('input[name="q"]').setAttribute('value', term);
document.querySelector('form[name="f"]').submit();
}, {
term: 'Chuck Norris'
});
casper.run();
再给个填没有name属性的input框框的例子:
casper.waitForSelector('#xx', function then() {
recognizedCode = 'xxx';
this.evaluate(function(rtCode){
document.querySelector('input[class="xxx"]').value = rtCode; //1>可以用这种方式填input框框(without name attribute)
//document.querySelector('a[action-type="submit"]')[0].click(); //2>可以在这里提交哦!
//__utils__.findOne('input[class="WB_iptxt oauth_form_input oauth_form_code"]').value = rtCode; //1>也可以这样填input框框(without name attribute)
}, {rtCode:recognizedCode});
this.click('a[action-type="submit"]'); //2>也可以在这里提交!
},
function onTimeout() {
this.log('wait selector timeout', 'error')
},
timeout = 1000
);
参考: https://groups.google.com/forum/#!msg/casperjs/iybL4kdLqVg/Exw8v2pcUXAJ
var casper = require("casper").create({
verbose: true,
logLevel: "debug",
onError: function(self,m){
this.capture("error.png");
console.log("FATAL:" + m);
self.exit();
}
});
还可以指定casper对象整个导航过程总的运行时间timeout,这样可以防止在程序因为网络原因或程序bug导致一直不退出,对应timeout的处理函数是onTimeout
与整个导航过程timeout和onTimeout相对应的是单步超时时间stepTimeout和单步超时处理函数onStepTimeout
require("utils").dump(xxx);
casperObj.cli.has(0)
casperObj.cli.get(3)
casperObj.cli.get('usename')
下面给个小例子
casper.on('resource.received', function(resource){
if (resource.redirectURL) {
var rUrl = resource.redirectURL;
if (rUrl.match(/\?code=(\w+)/g)) {
code = rUrl.substr(rUrl.search(/\?code=(\w+)/g)+6);
this.log("code=" + code,'info');
this.clear();
this.on('resource.received', function(resource) {});
} else
return;
} else
return;
});
9.单纯的把timeout设置得很长,而不设置对应的超时函数,那么设置的这个值是不起作用的,可能是casperjs的bug,实践多次证明过这个问题
比如,使用casperjsObj.waitForSelector()等待某个选择器时想定制timeout那么要提供onTimeout函数才行
10.实践证明一个casperjs程序内部无法创建多个casperjs对象
那么如果需要同时访问多个站点、且需要用一个站点的某些数据填写另一个站点某个form、且form页面在重新请求时不一样(比如验证码,用back()倒回去验证码就不一样了),怎么办呢?
鸟人的解决方案是自己提供一个页面内嵌两个frame分别装载目标站点;这里又有个问题是casperjs对象不能直接获取iframe内部的标签,需要用casperjsObj.page.switchToChildFrame(0/1/2)进入iframe、用casperjsObj.page.switchToParentFrame()回到上级iframe或者全局的位置(需要注意的是这两个函数和其他普通js程序一样、只有在导航过程中的某个function内部才有效,否则会被casperjs忽视,casperjs只认start/open/thenOpen/run/then/wait*/each/..等导航,普通js程序需要在这些导航对应的function内部填充)
11.capserjsObj.captureSelector()会有误差,可以根据casperjsObj.getElementBounds()获取要拍照的选择器的边界然后人工修订后把边界值传入casperjsObj.capture()拍照
12.控制导航跳向某一步、查看有多少步,可以用label/goto/dumpSteps函数,函数实现和用法详见https://github.com/yotsumoto/casperjs-goto
13.循环控制,我们不可避免的需要重复做一些动作,把所有的URL放到一个数组里面用each函数来处理当然不错,但是很有局限性,如果要重复的动作不是打开页面而是点击某个按钮呢?
鸟人想到的解决办法是用waitFor()+Wait()来实现循环,结果不太理想,要嘛卡死直到timeout,要嘛飞快的死循环
//loop:隔一段时间就刷新一次简历(用waitFor和wait实现循环,貌似不靠谱儿!)
/*
casper.waitFor(function check(){
this.wait(10000,
function() {
this.click('a[title="简历刷新"]');
this.log('refreshed my resume');
}
);
return false;
},
function then() {},
function onTimeout() {this.log('timeout: refresh loop competed.', 'error');},
timeout = 120000
);*/
参考:https://github.com/n1k0/casperjs/blob/master/samples/dynamic.js
function refresh()
{
this.wait(10000,
function() {
this.click('a[title="简历刷新"]');
this.log('refreshed my resume');
}
);
this.run(refresh);
}
casper.run(refresh);
14.日志中出现”Unsafe JavaScript attempt to access frame with URL”的info信息,启动casperjs时候加上参数--web-security=false(allow cross-domain XHR)即可(参见http://stackoverflow.com/questions/18960791/cant-run-a-basic-test-with-casperjs)
要治本的话,参见http://stackoverflow.com/questions/4324108/unsafe-javascript-attempt-to-access-frame-with-url,who care~