最近想做一个类似超级课程表的软件,研究了一下学校的URP系统,想通过URP获取课表,成绩等信息,
在网上查了下资料发现 android超级课程表原理(各大高校教务平台的数据获取原理)这篇文章,对我启发很大,但是获取的cookie不能使用,好像有些学校(比如山西农大)就不支持这样的做法,于是自己就又改进了一下,实现了应该所有高校的URP系统都能获取,在这里分享一下(本案例是使用android进行的操作,原理都一样,语言自选)
需要工具
流程:
首先看一下登陆界面
这里一共需要账号,密码, 验证码
登陆界面一开始是没有Cookie的,他会请求其他的地址,这里需要自己看Fildder,如我们的就是http://jwxt.sxau.edu.cn/dwr/interface/ajaxtool.js这个网址携带着Cookie,所以我们需要获取这个网址的Cookie
List cookies;
String urlyzm = "http://jwxt.sxau.edu.cn/dwr/interface/ajaxtool.js";
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
//* 建立HTTP GET连线 *//*
HttpGet httpRequest = new HttpGet(urlyzm);
try {
httpResponse = client.execute(httpRequest); //执行
// 若状态码为200 成功
if (httpResponse.getStatusLine().getStatusCode() == 200) { //返回值正常
// 获取返回的cookie
cookies = ((AbstractHttpClient) client).getCookieStore().getCookies();
Log.d("MainActivity", "statGetYam: success!!" + cookies.toString());
statGetImg();
}
} catch (Exception e) {
Log.d("MainActivity", "statGetYam: error!!!" + e);
}
cookies就是我们登陆界面的Cookie(未验证)
获取验证码的网站长这样http://jwxt.sxau.edu.cn/validateCodeAction.do?random=0.028191011294455448
可以看出后面random后面的是一窜随机数可以把后面的数字改一下就能用(如0.028191011294455447)
private void statGetImg() {
String uriAPI = "http://jwxt.sxau.edu.cn/validateCodeAction.do?random=0.6114370593559289"; //验证码的网站 后面的随机数可以自己设置
HttpGet httpRequest2 = new HttpGet(uriAPI);
try {
//将之前获取的未认证的Cookie添加到header中
httpRequest2.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
HttpResponse httpResponse2 = new DefaultHttpClient().execute(httpRequest2);
if (httpResponse2.getStatusLine().getStatusCode() == 200) {
StringBuffer sb = new StringBuffer();
HttpEntity entity = httpResponse2.getEntity();
InputStream is = entity.getContent();
//这里我在activity_main.xml定义了一个ImageView用来显示验证码
bitmap = BitmapFactory.decodeStream(is);
handler.sendEmptyMessage(1);
Log.d("MainActivity", "statGetImg success");
} else {
Log.d("MainActivity", "statGetImg error!" + httpResponse2.getStatusLine().getStatusCode());
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
我们要将数据发送http://jwxt.sxau.edu.cn/loginActionDD.do这个地址
可以看出在post数据时需要输入zjh(账号),mm(密码),v_yzm(验证码)
HttpClient client = new DefaultHttpClient();
HttpResponse httpResponse;
//* 建立HTTP Post连线 *//*
HttpPost httpRequest = new HttpPost(uriAPI);
List params = new ArrayList();
params.add(new BasicNameValuePair("zjh", "*******")); //这里的密码我用*取代了
params.add(new BasicNameValuePair("mm", "*******")); //这是密码
params.add(new BasicNameValuePair("v_yzm", "验证码")); //这是从图片中读取的验证码
try {
httpRequest.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
// 发出HTTP request
httpRequest.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
// 取得HTTP response
httpResponse = client.execute(httpRequest); //执行
// 若状态码为200 ok
if (httpResponse.getStatusLine().getStatusCode() == 200) { //返回值正常
Log.d("MainActivity", "startConnection: success!!! 认证成功" );
}
} catch (Exception e) {
Log.d("MainActivity", "startConnection: error!!!" + e);
}
这样就认证成功了 就可以获取自己所需的数据了
通过fiddler可以获取到自己查询成绩的url地址
通过把已认证的Cookie发送给这个url地址就可以获取到自己的成绩
我们学校用的是GET的请求方式,可以根据具体使用环境改成POST
String result = "";
String uriAPI = "http://jwxt.sxau.edu.cn/gradeLnAllAction.do?type=ln&oper=fainfo&fajhh=627"; //这个地址就是成绩的地址
HttpGet httpRequest2 = new HttpGet(uriAPI);
try {
httpRequest2.setHeader("Cookie", "JSESSIONID=" + cookies.get(0).getValue());
HttpResponse httpResponse2 = new DefaultHttpClient().execute(httpRequest2);
if (httpResponse2.getStatusLine().getStatusCode() == 200) {
StringBuffer sb = new StringBuffer();
HttpEntity entity = httpResponse2.getEntity();
InputStream is = entity.getContent();
BufferedReader br = new BufferedReader(new InputStreamReader(is, "GB2312"));
//是读取要改编码的源,源的格式是GB2312的,安源格式读进来,然后再对源码转换成想要的编码就行
String data = "";
while ((data = br.readLine()) != null) {
sb.append(data);
}
result = sb.toString(); //此时result中就是我们成绩的HTML的源代码了
Log.d("MainActivity", "startConnection xml success" + result);
} else {
Log.d("MainActivity", "startConnection error!" + httpResponse2.getStatusLine().getStatusCode());
}
} catch (Exception e) {
Log.d("MainActivity", "startConnection xml error" + e);
}
注意:
如果不进行验证码的验证直接发送账号密码也可以进去,只是不能进行信息的读取,会一直返回这样的500错误
500 Servlet Exception
500 Servlet Exception
java.lang.NullPointerException
at zhjw.grade.search.GradeLnAllAction.execute(GradeLnAllAction.java:45)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:226)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1164)
at org.apache.struts.action.ActionServlet.doGet(ActionServlet.java:397)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:115)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:92)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:106)
at zhjw.util.filter.CharacterEncoding.doFilter(CharacterEncoding.java:108)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at zhjw.util.filter.UserAuthBase.doFilter(UserAuthBase.java:39)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.zfsoft.zfca.tp.cas.client.filter.ZFSSOFilter.doFilter(ZFSSOFilter.java:103)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.zfsoft.zfca.tp.cas.client.logout.SingleSignOutFilter.doFilter(SingleSignOutFilter.java:100)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at zhjw.util.filter.newfilter.UrpsoftFilter.doFilter(UrpsoftFilter.java:96)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:173)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)
at com.caucho.server.hmux.HmuxRequest.handleRequest(HmuxRequest.java:420)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:514)
at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:520)
at com.caucho.util.ThreadPool.run(ThreadPool.java:442)
at java.lang.Thread.run(Thread.java:619)
Resin-3.0.27 (built Mon, 19 Jan 2009 01:26:35 PST)
以上