实现原理分析:
我们抓取数据,就是用代码去模拟浏览器登录,及点击链接的一步步操作,把返回的HTML数据进行解析,得到我们想要的内容,即一个简单的网络爬虫。只要熟悉http协议,熟悉web项目的开发过程。我们可以借助工具如IE插件HttpWatch、浏览器自带的开发者工具抓包分析请求过程,通过HttpClient来模拟浏览器请求,Jsoup解析网页内容,这里还要注意Cookie和Referer的使用。
HttpClient的使用过程:
1.创建GET或POST请求。
2.为请求设置头信息,设置要提交的参数。
3.创建浏览器client对象,并执行。
关于Jsoup:
可以解析文本网页内容的工具类,类似于js的选择器,可以通过id、正则表达式、选择器等来获取文本内容。
关于验证码:
在大约2016.3.25之前正方教务是有个验证码的Bug的,后台没有验证码为空字符串的校验,所以轻松搞定。后来又去测试发现代码不行了,分析了一下返回的内容,竟然有了非空校验,另外,有篇文章所写的http://jwgl.XXX.edu.cn/default2.aspx把default2改成default6是不带验证码的入口,现在也已经不行了。那也无所谓,只要把验证码提前下载好,让用户手动输入就可以了,课程格子,超级课程表都是这么干的。
另外:当我们用浏览器登录,浏览器遇到验证码的img标签的src会去自动请求这个地址,产生验证码。而验证码的值一般是放在Session里,默认有效期是30min,但如果用Httpclient去请求他是不会解析这个地址的,所以只去请求主页,此时验证码为空,这也就是最开始为什么不用输入验证码的原因。即便需要验证码,我们也可以先下载验证码,让用户输入,或者orc识别。
关于Cookie和Referer:
其实这里的cookie并不是我们通常自己设置的cookie,而是sessionID,sessionID用来判断是同一次会话session是保存在服务器端的,它有一个生命期,客户端的cookie只是保存了id信息,关闭浏览器时,服务器端的session只要还在同一个生命期内还是同一次会话。请求登录页面如果不带着这个Cookie也就是sessionID是不行的,如果不从主页开始抓包分析,忽略了这点,会直接郁闷到死啊,坑!另外这个Cookie要和验证码保持一致,也就是如果你用浏览器去请求验证码,再手动输入到代码的参数,是不行的。因为浏览器去请求就会产生对应的Cookie和验证码,如果再用httpclient去请求主页获取Cookie,再去请求登录页面,虽然此时验证码并没有刷新。但两个Cookie是不一致的。关于Referer,Referer表示从哪个地址来的,一开始的时候我设置请求头信息,没有加Referer结果不行,后来加上就可以了。说明他后台有验证,这里注意加上就好了。
关于要提交的信息:
提交的信息有 头信息和表单信息,对于头信息,我们只需要提交Cookie和Referer就可以了。表单信息要全部提交。
大体实现过程是:
1.通过抓包分析获取每一个功能所对应的网址,及form表单提交数据,再带上头信息Cookie和Referer。2.创建GET或POST请求,给请求设置参数和头信息,创建client,执行client。3.把返回的内容解析按照相应的编码格式解析成字符串。4.用Jsoup解析返回的网页节点,获取想要的信息。
这里用的是纯JavaSe代码,可以移植到Web端或Android端,先附一张结果图:
以下以济南大学教务管理系统为例分析请求过程:
登录功能过程分析:
第一次请求主页:
第一次请求验证码页:
【如果先去请求主页,我们要带着Cookie去请求验证码页面。如果直接去请求验证码页面,它同时也产生了Cookie,所以我们第一步应该是:直接请求验证码页面,获取Cookie和验证码。】接下来:
请求登录页面http://jwgl2.ujn.edu.cn/default2.aspx:
【请求登录页面要带着Cookie和表单提交的数据也就是图中的FormData,返回的状态码是302,也就是发生了重定向,重定向到了http://jwgl2.ujn.edu.cn/xs_main.aspx?xh=学号,注意这里的参数有一个是_VIEWSTATE,其实每个表单都有一个_VIEWSTATE参数,由于鄙人不熟悉asp.net,也不清楚他是干嘛用的,但可以肯定的是,这个参数在一段时间后会变化,所以我们要先来获取这个参数,代码都在最后。】
至此,登录功能完成。
查询个人成绩过程分析:
点击信息查询--成绩查询抓包分析:
【地址栏没有变化,而抓包地址是http://jwgl2.ujn.edu.cn/xxjsjy.aspx?xh=学号&xm=姓名&gnmkdm=xxxxx,说明这是一个请求转发,Request头信息包含第一次获取的Cookie,填上相应的Referer,所以只需要设置头信息Cookie和Referer以及表单提交的信息去post请求http://jwgl2.ujn.edu.cn/xxjsjy.aspx?xh=学号&xm=姓名&gnmkdm=xxxxx就可以了。】
【然后我们可以把返回的流转化为字符串,通过Jsoup解析每一个td标签。得到我们想要的内容。】
至此,查询个人成绩功能完成。那么,查询空教室,个人课表等跟这个过程一样。
教务管理系统也是在不断更新的,不保证下面的代码以后还可以用,刚开始做我也被网上的代码误导过,但弄清楚了原理仔细分析一下就好了。
实现代码,见http://www.oschina.net/code/snippet_2688363_55215#81604