CasperJS-程序员宅基地

技术标签: 前端  

概述 

       项目组有个网络爬虫的需求,Java有个爬页面的Jsoup,虽然可以一定程度上借助cookie,sessionId,TCP/IP通信等相关实现一定程度上的模拟浏览器行为,但作为服务器开发语言,在前端交互上,显然不能挥洒自如.老大推荐了CasperJs,同事在搞,顺便也偷喵的学习下.

      CasperJs 是一个开源的导航脚本处理和测试工具,基于PhantomJS(前端自动化测试工具)编写.CasperJS简化了完整的导航场景的过程定义.提供了用于完成常见任务的实用的高级函数,方法和语法.

       Phantomjs 一个基于webkit内核的无头浏览器,提供Headless Testing,Screen Capture,Page Automation,Network Monitoringj 解决方案.

       Phantomjs 提供javascript API,通过js就可以实现与Phantomjs交互,而CasperJs 用js开发的脚本工具,其功能的实现依赖Phantomjs API.因此利用Caperjs 进行爬虫,其核心还是Phantomjs.

环境搭建

      学习之用,window环境搭建
  • 下载phantomjs (官网下载太慢,镜像下载),选择下载window版-phantomjs-2.1.1-windows.zip
  • 下载Casperjs - -casperjs-1.1.4-1
  • 解压以上压缩包,配置环境变量(到bin目录下)
  • cmd 分别执行phantomjs --version 与casperjs --version,有返回值,即安装成功
        js测试.编写sample.js
var casper = require('casper').create();
casper.start('http://casperjs.org/');

casper.then(function() {
    this.echo('First Page: ' + this.getTitle());
});

casper.thenOpen('http://phantomjs.org', function() {
    this.echo('Second Page: ' + this.getTitle());
});

casper.run();
        在sample.js的目录下执行cmd命令 casperjs  sample.js,即可看到返回值
First Page: CasperJS - a navigation scripting & testing utility for PhantomJS and SlimerJS written in Javascript
Second Page: PhantomJS | PhantomJS
         至此,安装成功.

使用

    官网很详细,例子也很多
    
       phantomjs documentation
小案例,测试登录163邮箱(测试登录成功,但测试写信失败了...)
phantom.outputEncoding = "GBK"; //设置编码
var fs = require('fs'); //来自phantomjs model
var utils = require('utils'); //casperjs 自身的model
var casper = require('casper').create({
		verbose: true,
		silentErrors: true,
		//logLevel: "info", //日志级别
		viewportSize: {width: 800, height: 600},
		clientScripts: [//这里可以随意设置你的自定义js文件
			'jquery-3.2.1.min.js' //可在evaluate 方法中使用(注入到page中)
			//'polyfill.min.js'
		],
		pageSettings: {
			loadImages: true, //加载图片
			loadPlugins: true, //插件
			XSSAuditingEnabled: false,
			localToRemoteUrlAccessEnabled: false,
			//userAgent: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36' //伪造头
			userAgent: 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0' //伪造头
		},
		onError: function (casper, msg, backtrace) {
			this.echo("onError msg:", msg);
			backtrace.forEach(function (i, index) {
				this.echo("onError backtrace:", msg);
			});
		},
		onLoadError: function (casper, requestUrl, sta) {
			casper.echo("onLoadError requestUrl: " + requestUrl);
			casper.echo("onLoadError status :" + sta);
		},
		onResourceRequested: function (casper, resource,request) { //处理请求,如不加载一些adobe无关url
			var skip = [
				'adobe.com',
				'web.yixin'

			];
			skip.forEach(function (needle) {
				if (resource.url.indexOf(needle) > 0) {
					casper.echo('abort: ' + needle);
					request.abort();
				}
			})
		}
	});
	
	
var email = "****";//163邮箱
var password = "*****";//密码
var sendEmail = "****";


//var page = webPage.create(); //在casperjs启动后,自动创建一个page 可以使用casper.page获取(options 中有page 默认为空)

casper.start("http://mail.163.com/", function () {
	this.echo("loaded : " + new Date());
	//print console.log
	this.page.onConsoleMessage = function (e) {
		console.log(e);
	}
});
casper.waitForSelector("#x-URS-iframe", function () {
	//登录iframe,指的是#x-URS-iframe
	this.switchToFrame(3); //进入登录的iframe
	this.echo("frameName  "+ this.page.frameName);

	this.waitForSelector("form#login-form", function () {
		//填充登录表单
		this.fill('form#login-form', {
			'email': email,
			'password': password,
		}, false);

		//点击登录按钮
		this.click("#dologin");

		this.wait(2000, function () {
			//登录名
			if (this.exists("span[id$='_dvGreetName']")) {
				this.echo("login success username:  " + this.fetchText("span[id$='_dvGreetName']"));
/* 				var flag=this.evaluate(function(){ //jquery用法,在phantomjs的方法中使用
					console.log("login success username:  " + $("span[id$='_dvGreetName']").html());
					return true;
				}); */
			} else {
				this.echo("login fail");
			}

			//点击写信
			this.click("li.js-component-component.ra0.mD0 > span.oz0");

			this.wait(2000, function () {

				//以下测试写信,不过失败了
				this.wait(2000, function () {
					casper.waitForSelector("div[id^='_mail_toolbar_']", function () {
						//进入写信页面
						this.echo("access writer letter page");
						this.wait(2000, function () {
							this.capture("1.png");
							this.sendKeys("div[id^='_mail_input_'] > input[id$='_subjectInput']", 'hello'); //发信主题

							//填写发送邮箱的时候失败了,页面上填写完邮件,有绑定事件检测你填写的邮箱格式,然后包装你的邮箱(用em标签包装),但casperjs模拟此行为失败
							this.sendKeys("input.nui-editableAddr-ipt", sendEmail); //发送qq邮箱


							this.switchToFrame(4);
							this.sendKeys("body.nui-scroll", '123');
							
							this.switchToMainFrame();
							//this.switchToParentFrame();
							
							this.echo(this.exists("div[id^='_mail_input_'] > input[id$='_subjectInput']"));
							this.echo(this.exists("input.nui-editableAddr-ipt"));
							
							this.echo("frameName  "+ this.page.frameName);

							this.wait(3000, function () {
								this.capture("2.png");
								//点击发送按钮
								this.click("div.nui-toolbar-item > div.js-component-button.nui-mainBtn.nui-btn.nui-btn-hasIcon.nui-mainBtn-hasIcon  >  span.nui-btn-text");

								this.wait(3000, function () {
									this.capture("3.png");
								})
							});
						});
					}, function () {
						this.echo("access writer letter page fail").exit();
					}, 10000);
				});
			});
		})

	}, function () {
		this.echo("form#login-form not found").exit();
	}, 10000);
});

casper.run(function () {
	this.echo("end").exit();
});


      

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_33854869/article/details/77976717

智能推荐

Android Studio 初学问题总结(更新中_android studio新手常见问题-程序员宅基地

1.解决在android开发环境中出现should use @string resourceandroid建议引用全局变量 即将要写的东西写在strings文件中,例如:android:text="@string/text"strings文件中:<string name="text">你要写的东西</string>2.error: failed linking..._android studio新手常见问题

WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】-程序员宅基地

WCF Interview Questions – Part 4 This WCF service tutorial is part-4 in series of WCF Interview Questions. Before reading this please go through the following articles in this series.这是WCF...

UltraEdit 25以后的版本 绕过试用期_ultraedit 系统可能修改绕过激活-程序员宅基地

来源于https://blog.csdn.net/CoderAldrich/article/details/79725475针对版本v而是哦你24以后的版本无法通过注册机离线注册问题,通过x32/64dbg修改补丁文件,绕过注册判断逻辑。试用后没有再弹出“剩下试用期X天”的提示,直接可试用!打开x32/64dbg-&gt;文件+附加-&gt;“符号”里找到负责判断的链接库:..._ultraedit 系统可能修改绕过激活

以太坊私有链搭建-程序员宅基地

为什么80%的码农都做不了架构师?>>> ...

【Qt】用QT实现两个按钮控制两个界面的交替出现_qt一个按钮控制其他按钮的出现-程序员宅基地

【主要思路】这里介绍的是主副两个界面,通过父界面发送信号给主界面,实现其中某一个界面的显示与隐藏mainwidget.h#ifndef MAINWIDGET_H#define MAINWIDGET_H#include <QWidget>#include <QPushButton>#include "subwidget.h" //主窗口包含副窗口头文件..._qt一个按钮控制其他按钮的出现

Protobuf协议应用干货-程序员宅基地

为什么80%的码农都做不了架构师?>>> ..._前后端proto协议定义一般用哪些

随便推点

Android Parcelable(传递Bitmap)应用_bitmap parcelable_王富贵王富贵王富贵的博客-程序员宅基地

先不废话先上代码吧! 我们就不讲intent的传递方式了因为这个很常见Parcelablepublic class NewsBean implements Parcelable { public String name; public int age; public String profession; public byte[] bytesFromBitmap; public NewsBean(Parcel in) { name = i_bitmap parcelable

linux lsmod命令 及相关信息-程序员宅基地

lsmod (list modules)语法:lsmod功能:lsmod命令:是一个小程序,用来显示文件、proc/modules的信息,也就是显示当前内核模块装载的模块。补充说明:执行lsmod指令,会列出所有已载入系统的模块。Linux操作系统的核心具有模块化的特性,应此在编译核心时,务须把全部的功能都放入核心。您可以将这些功能编译成一个个单独的模块,待需要..._linux 脚本获取指定lsmod

库卡机器人配重_干货 | 库卡机器人使用教程-程序员宅基地

21世纪的今天,机器人离我们的生活越来越近,越来越多的工作正在被机器人所取代,同时也让很多人感到焦虑,焦虑的是自己的工作如何才能不被机器人所取代呢?我觉得,解决这个问题的最好办法就是自己主动去学习机器人,去掌握一门机器人无法代替得技术。那么从今天开始就跟着我一起来学习工业机器人如何使用吧!(本教程以库卡机器人为说明对象)下面开始我们的第一章学习内容:一、KUKA 机器人系统的结构和功能1.1机器人..._库卡机器教程

DOM/BOM-程序员宅基地

DOM对象与方法、节点与遍历树、DOM选择器、DOM节点增删改查、DOM样式操作、DOM位置获取与偏移、DOM对象与标签区别、DOM虚拟化、DOM事件、Event对象、定时器与监听器、事件委托、事件代理、事件分流、事件冒泡、默认行为、事件捕获、防抖、节流、滚动、键盘行为、事件降频、行为锁机制、拖拽模组、碰撞检测、距离判断、三角函数、方向判断、运动框架、弹性运动、重力加速度、DOM树、CSSOM树、渲染解析、加载、回流、重绘、浏览器线程与阻塞。BOM

centos7部署mysql-5.7.20-程序员宅基地

1.创建目录及用户useradd mysql -s /sbin/nologin -Mmkdir /toolsmkdir /usr/local/mysql-5.7.20/{conf,tmp} -pmkdir /data/mysql-5.7.20/data -p2.下载软件cd /toolswget https://dev.mysql.com/get/Downloads/MySQL-5....

Json转Hashtable的转换-程序员宅基地

json 转换为Hashtable /// <summary> /// Json转Hashtable /// </summary> /// <param name="json"></param> /// <returns></returns...