这是在博客园里开博以来写的第一篇博客。html
由于以前看过不少人都有发过关于模拟登陆正方软件获取数据的文章,本身以为挺好玩的便也去动手一作,开始还觉得挺难的,但实际作起来还蛮简单的,固然其中还有些小插曲。浏览器
废话很少说,先po两张效果图:工具
界面作得比较随意,有空会再完善的。post
接下来便说说是如何实现的了。学习
首先,你得有个抓包工具(其实用浏览器自带的f12工具应该也是能够的,就是比较麻烦),不少人都是用Httpwatch(貌似支持IE跟火狐),这里我就随波逐流,也用Httpwatch。安装好Httpwatch以后即可以直接打开浏览器登陆教务系统抓包啦测试
在点击登陆按钮的时候记得先点击记录。spa
登陆进去以后即可以看到Httpwatch中有数据变化了。pwa
这时先选中方法为Post的这一行(记下此时的URL,后面有用到),再选中Post数据来看看要提交的表单有哪些。code
这里面咱们只要用到上面圈出的五个参数。orm
第一个参数“_VIEWSTATE”要本身得到(获取登陆首页的html内容而后在里面提取就好了);
第二个参数RadioButtonList1的乱码数值实际上是“学生”(有的Httpwatch版本能够显示,有的则是乱码),提交表单时提交“学生”便可;
第三个参数TextBox2是密码;
第四个参数txtSecretCode是登陆界面的验证码,有的学校系统能够直接绕过,我学校的则不行(开始看了别人的说能够直接填空写死,结果在这里被坑了很久,最后只能老老实实把验证码加上去),因此具体可不能够还得本身试试;
第五个参数是学号;
(每一个学校提交的参数应该都是不一样的,不过依葫芦画瓢就好了)
其实表单中还有一个更重要的参数:Cookie
Cookie的值在每一次提交的时候都得加上去,Cookie同“_VIEWSTATE”同样得本身先得到,不过不同的是Cookie获取一次就能够,但“_VIEWSTATE”必须每次提交都得获取一次。
如今就来提交表单尝试登陆
String URL = "http://jwgl.gdut.edu.cn/default2.aspx";//上面说到的URL HttpPost mHttpPost = new HttpPost(URL);//创建链接 mHttpPost.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);//禁止重定向 mHttpPost.setHeader("Cookie", Cookie);//设置Cookie //填写表单 List<NameValuePair> list = new ArrayList<NameValuePair>(); list.add(new BasicNameValuePair("__VIEWSTATE",viewstate)); list.add(new BasicNameValuePair("txtUserName",学号)); list.add(new BasicNameValuePair("TextBox2", 密码)); list.add(new BasicNameValuePair("RadioButtonList1","学生")); list.add(new BasicNameValuePair("txtSecretCode", 验证码)); //下面几个都直接填空写死便可(事实上下面几个只需添加Button1便可) list.add(new BasicNameValuePair("Button1", "")); list.add(new BasicNameValuePair("lbLanguage", "")); list.add(new BasicNameValuePair("hidPdrs", "")); list.add(new BasicNameValuePair("hidsc", "")); mHttpPost.setEntity(new UrlEncodedFormEntity(list, "GBK"));//提交表单 HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost);// 响应请求 int statusCode = mHttpResponse.getStatusLine().getStatusCode();//状态码若为200则表示登陆失败,此时需检查是否表单有误;若状态码为302则表示成功
当上述状态码为302时可继续往下,若为200请继续检查测试。
实际上要用到的地址是刚刚302下面的跳转的地址
咱们再来对它创建链接尝试登陆
String URL = "http://jwgl.gdut.edu.cn/xs_main.aspx?xh=" + 学号; HttpPost mHttpPost = new HttpPost(URL);//这里用post跟get均可以 //这里要比上次多添加一个值“Referer”,即将它的值置为此时的URL地址 mHttpPost.setHeader("Referer", URL); mHttpPost.setHeader("Cookie", Cookie);//Cookie仍是原来的值 HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost);//响应请求 //此时的状态码若为200则表示成功登陆进入教务系统 if (httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity mHttpEntity = mHttpResponse.getEntity(); String html = EntityUtils.toString(mHttpEntity);//获取网页内容 String studentName = Jsoup.parse(html).getElementById("xhxm").text();//获取学生名字,后面查询成绩时须要用到 }
登陆成功以后再回到浏览器先把刚刚抓取的数据清空,再从新点击记录,再进行成绩的查询,即可以抓取到数据了
一样咱们找到方法为Post的这一行,选中它,同时记下它的URL,一样再在下面选中Post数据来看看须要提交的表单
这时咱们须要提交的参数有上面四个,
第一个参数“_VIEWSTATE”一样须要本身从新得到(注意,这里的参数已经跟上面的不同了,此时应该获取的是登陆成功后的页面的html内容,而后再提取便可);
第二个参数Button1又乱码了,其实是刚刚三个按钮的值
第三个参数ddlXN是学年;
第四个参数ddlXQ是学期;
(在这里若是点击按学期查询,那么就必须提交第三个跟第四个参数;若是点击按学年查询,那么就必须提交第三个参数;若是点击在校学习成绩查询,那么第三个跟第四个参数都不用提交,因此咱们能够在代码中加个判断)
接下来咱们用已有的参数来创建链接:
String URL = "http://jwgl.gdut.edu.cn/xscj.aspx?xh=" + 学号 + "&xm=" + 学生姓名 + "&gnmkdm=N121605";//学生姓名就是上面获取到的studentName HttpPost mHttpPost = new HttpPost(URL); //填写表单 List<NameValuePair> list= new ArrayList<NameValuePair>(); list.add(new BasicNameValuePair("__VIEWSTATE", viewstate)); list.add(new BasicNameValuePair("Button1", "按学期查询"));//这里我用学期查询,所以须要添加下面两个参数 list.add(new BasicNameValuePair("ddlXN", "2014-2015")); list.add(new BasicNameValuePair("ddlXQ", "1")); mHttpPost.setEntity(new UrlEncodedFormEntity(params, "GBK"));//提交表单 //这里咱们一样须要设置两个头信息。后面的套路跟前面的是差很少的 mHttpPost.setHeader("Referer", "http://jwgl.gdut.edu.cn/xs_main.aspx?xh=" + 学号); mHttpPost.setHeader("Cookie", Cookie); HttpResponse mHttpResponse = new DefaultHttpClient().execute(mHttpPost); HttpEntity mHttpEntity = mHttpResponse.getEntity(); String html = EntityUtils.toString(mHttpEntity);//此时就获取到含有成绩信息的页面了 //用Jsoup将里面的课程成绩提取出来 Elements mElements = Jsoup.parse(html).select("td"); //再根据须要向mElements中提取须要的数据,再将其添加到listview中就大功告成了
固然,实现了成绩查询,其余的功能像什么课表查询、考试查询也均可以一一实现了,原理都是差很少的。