本文共 4343 字,大约阅读时间需要 14 分钟。
转自:http://blog.csdn.net/xiarendeniao/article/details/7740375
官网
分享
环境:
- [dongsong@localhost ~]$ casperjs --version
- 1.0.0-RC2
- [dongsong@localhost ~]$ phantomjs --version
- 1.7.0
1.casperjs按照start()、then*()、wait*()、open()等流程往下做导航(注意,如果有语法错误,比如少个分号神马的,可能运行时就无任何提示的卡那里了) run()方法触发该流程,run()方法可以指定一个onComplete()方法供导航完成时回调 exit()/die()退出 2.打印html源码可以用debugHTML();打印web页面用debugPage();获取网页快照用capture('xx.png') 3.填写表单或者输入框用fill()做(要求文本框有name属性)或者在evaluate()内部做(evaluate相当于casperjs和网页之间的gate) 提交表单可以通过fill直接完成(有些提交是js控制的,这种方法就行不通了)或者用click()点击提交按钮
下面给一个在evaluate内部做的例子(跟普通页面上的js编程类似)
-
- 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;
-
-
- }, {rtCode:recognizedCode});
- this.click('a[action-type="submit"]');
- },
- function onTimeout() {
- this.log('wait selector timeout', 'error')
- },
- timeout = 1000
- );
参考:
4.日志console.log();或者由casperjs对象调用log()/echo()方法 创建capserjs对象时可以指定日志级别、日志详尽程度、定制事件回调函数(OnError/onResourceReceived/httpStatusHandlers/...): - 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
5.调试时免不了要打印变量或者对象的信息 - require("utils").dump(xxx);
6.命令行参数由cli模块操作,详见 - casperObj.cli.has(0)
- casperObj.cli.get(3)
- casperObj.cli.get('usename')
7.selector,跟css选择器规则一样(详见谷歌/度娘) #xx 选取以xx为id的html标签 xx[attr='value'] 选取属性attr值为value的xx类型html标签 .xx 选取以xx为class的html标签 8.事件,用casperObj.on()来注册事件的回调函数,详见 要清除对某时间的监控和回调可以把回调函数设为空 下面给个小例子
- 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函数,函数实现和用法详见
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
- );*/
网上寻来的解决方案是递归调用,casperjsObj调用run函数时可以传入一个结束时执行的函数,在这个函数里面可以加入【我们的循环体】和【递归的run调用】
参考:
- 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)即可(参见)
要治本的话,参见,who care~