项目叙述
通过HttpClient、Jsoup、AJAX等技术,实现获取辽宁大学课程表,并呈现出来。

成功登录后,提示

课表展现:

实现原理简述
1.分析目标源文件

得知登录是用post方法向https://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login发送请求,带有两个参数stuid和pwd分别对应学号和密码

获取课表是向https://jwgl.lnu.edu.cn/pls/wwwbks/xk.CourseView请求
这个用get方法就可以。
2.模拟登录,并获取课表
使用HttpClient模拟post登录,再模拟get请求获取课表的地址
学生选课系统信息学院 软件工程专业 刘之帅(161407212)
你共选择了 28 学分
已经安排时间地点的课程:
星期一星期二星期三星期四星期五星期六星期日
第一节
高等数学(下)(必修)/王敏16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选高级语言程序设计(必修)/宣伟宏高等数学(下)(必修)/王敏16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选普通物理A(上)(必修)/张美霞15级数学院、16级信息学院(除信息管理),16测控、16电科、16电气专业学生选大学英语(二)(必修)/初彦霞16级崇山校区学生选
第二节高级语言程序设计(必修)/宣伟宏普通物理A(上)(必修)/张美霞15级数学院、16级信息学院(除信息管理),16测控、16电科、16电气专业学生选大学英语(二)(必修)/初彦霞16级崇山校区学生选
高等数学(下)(必修)/王敏16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选
第三节
马克思主义基本原理(必修)/王晓红16级崇山校区学生选
离散数学(必修)/朱红宁离散数学(必修)/朱红宁
第四节体育(二)(必修)/王越鹏网球,崇山校区军事理论(必修)/金一哲16级崇山校区学生选
马克思主义基本原理(必修)/王晓红16级崇山校区学生选创新性思维与创新方法(任选)/刘畅崇山校区
第五节
第六节
第七节
时间地点如下
课程名称选课限制说明课程号课序号课程属性考试类型上课地点上课时间上课周次
高等数学(下) 16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选0920426 3 必修 考试 蕙星楼419 1-1 全周上课
高等数学(下) 16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选0920426 3 必修 考试 蕙星楼419 5-2 全周上课
高等数学(下) 16级信息学院(除信息管理专业),16测控、16电科、16电气、16环境工程专业学生选0920426 3 必修 考试 蕙星楼419 3-1 全周上课
普通物理A(上) 15级数学院、16级信息学院(除信息管理),16测控、16电科、16电气专业学生选1010014 3 必修 考试 东配楼403 4-1 全周上课
普通物理A(上) 15级数学院、16级信息学院(除信息管理),16测控、16电科、16电气专业学生选1010014 3 必修 考试 东配楼403 2-2 全周上课
高级语言程序设计
1410044 4 必修 考试 东配楼103 1-2 1-13周上
高级语言程序设计
1410044 4 必修 考试 东配楼301 2-1 1-13周上
离散数学
1420053 2 必修 考试 蕙星楼319 4-3 单周上课
离散数学
1420053 2 必修 考试 蕙星楼319 5-3 全周上课
大学英语(二) 16级崇山校区学生选2111024 6 必修 考试 蕙星楼301 3-2 全周上课
大学英语(二) 16级崇山校区学生选2111024 6 必修 考试 蕙星楼301 5-1 全周上课
马克思主义基本原理 16级崇山校区学生选2210153 3 必修 考试 东配楼501 2-3 全周上课
马克思主义基本原理 16级崇山校区学生选2210153 3 必修 考试 东配楼501 4-4 双周上课
体育(二) 网球,崇山校区2310021 19 必修 考试
1-4 全周上课
军事理论 16级崇山校区学生选2310051 4 必修 考试 蕙星楼601 2-4 全周上课
创新性思维与创新方法 崇山校区F490022 2 任选 考查 东配楼302 5-4 2,6,10,15周上
操作成功!
通过观察得知,课表信息在第二个table元素里面,而且所有课表信息的bgcolor都是#EAE2F3,同时,font元素里面的内容并不是我们需要的。
所以,我们使用jsoup解析出所有bgcolor是#EAE2F的td并删除里面的font元素,获取这些元素的text,存到数组中。
public List DealInfo(String Info){ List result = new ArrayList(); Document doc = Jsoup.parse(Info); Element table = doc.select("table").get(1); table.select("font").remove(); Elements tds = table.select("td[bgcolor=\"#EAE2F3\"]"); for (Element td : tds) { result.add(td.text()); // System.out.println(td.text()); } return result; } 3.将数组转变成json 4.前端ajax请求,获取json转化为数组 后台源码 Dodeal.java package src.lnu.lzs.deal; import java.io.IOException; import java.util.ArrayList; import java.util.List; import net.sf.json.JSONArray; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class Dodeal { private HttpUtils httpUtils = new HttpUtils(); /* * 判断是否登录成功 * @param username 用户名 * @param password 密码 * @return boolean */ public boolean Succeed(int username,String password){ String param = "stuid="+username+"&pwd="+password; boolean succeed = true ; try { String htmlTxt = httpUtils.sendPost("https://jwgl.lnu.edu.cn/pls/wwwbks/bks_login2.login", param); Document doc = Jsoup.parse(htmlTxt); Elements body = doc.select("body"); String bodyText = body.text(); System.out.print(bodyText); if(bodyText.equals("你输入了错误的学号或密码,不能登录!")){ succeed=false; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return succeed; } /* * 获取课表信息 * @return HTML代码 */ public String getInfo() throws IOException{ String html = httpUtils.sendPost("https://jwgl.lnu.edu.cn/pls/wwwbks/xk.CourseView",""); httpUtils.close(); return html.replace(" ", " "); } /* * 将课表HTML处理成数组 * @param HTML代码 * @return 数组 */ public List DealInfo(String Info){ List result = new ArrayList(); Document doc = Jsoup.parse(Info); Element table = doc.select("table").get(1); table.select("font").remove(); Elements tds = table.select("td[bgcolor=\"#EAE2F3\"]"); for (Element td : tds) { result.add(td.text()); // System.out.println(td.text()); } return result; } /* * 将数据处理成json * @param 数组 * @return json */ public String ListToJosn(List temp){ JSONArray jsa = JSONArray.fromObject(temp); System.out.print(jsa); return jsa.toString(); } } HttpUtils.java package src.lnu.lzs.deal; import java.io.IOException; import java.io.InputStream; import java.net.URL; import org.apache.catalina.connector.InputBuffer; import org.apache.http.HttpEntity; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.util.PublicSuffixMatcher; import org.apache.http.conn.util.PublicSuffixMatcherLoader; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.LaxRedirectStrategy; import org.apache.http.util.EntityUtils; public class HttpUtils { private CloseableHttpClient httpClient = HttpClients.custom() .setRedirectStrategy(new LaxRedirectStrategy()) .build(); private CloseableHttpResponse response = null; /** * sendPost 发送post请求 * @param url * @param param * @return * @throws IOException */ public String sendPost(String url, String param) throws IOException { String result = null; // try { HttpPost hp = new HttpPost(url); RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000) .setConnectTimeout(15000) .setConnectionRequestTimeout(15000) .build(); StringEntity stringEntity = new StringEntity(param, "UTF-8"); stringEntity.setContentType("application/x-www-form-urlencoded"); stringEntity.setChunked(false); hp.setEntity(stringEntity); hp.setConfig(requestConfig); response = httpClient.execute(hp); System.out.println(response.getStatusLine()); result = EntityUtils.toString(response.getEntity(), "UTF-8"); } catch (Exception e) { e.printStackTrace();// TODO: handle exception }finally{ } return result; } public void close() throws IOException { httpClient.close(); response.close(); } } TheServlet.java package src.lnu.lzs.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import src.lnu.lzs.deal.Dodeal; /** * Servlet implementation class TheServlet */ @WebServlet("/TheServlet") public class TheServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public TheServlet() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // System.out.println("调用get方法:"); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("POST方法"); Dodeal dodeal = new Dodeal(); int stdId =Integer.parseInt(request.getParameter("username")); String password = request.getParameter("password"); boolean succeed = dodeal.Succeed(stdId, password); if(succeed){ String html = dodeal.getInfo(); String result = dodeal.ListToJosn(dodeal.DealInfo(html)); response.setContentType("text/html;charset=utf-8"); response.getWriter().println(result); }else{ response.setContentType("text/html;charset=utf-8"); response.getWriter().print("NULL"); } } }