本次实例主要是对于接入青果系统的某高校教务系统进行期末成绩爬取,本次模拟学校为延安大学西安创新学院的教务系统,实现语言为java,前端框架采用jquery+layerui,后端框架为springboot + redis + mysql 图形验证码识别用的百度AI

  • 登录教务处系统
  • 识别验证码
    • 识别图片
  • 模拟登录
  • 爬成绩接口

注:切勿用入商业用途,否则后果自负

登录教务处系统

  1. 经过百度拿到该学校的教务处系统,即http://www.xacxxy.com:88/jwweb/
  2. 通过F12拿到该系统的前端渲染后的代码,即 view-source:http://www.xacxxy.com:88/jwweb/_data/index_LOGIN.aspx
  3. 找到输入用户名和密码的input框,然后解析和解密,从输入框可以看到输入的内容传到后台是通过一系列加密的,于是拿到其加密算法,
  4. 拿到这个,其实已经成功了一大半了,于是解析一下这一段内容
function chkpwd(obj) {if (obj.value != '') {//对学号进行md5加密并且转成大写 然后再拼接上该学校的代码var s = md5(document.all.txt_asmcdefsddsd.value + md5(obj.value).substring(0, 30).toUpperCase() + '13683').substring(0, 30).toUpperCase();document.all.dsdsdsdsdxcxdfgfg.value = s;} else {document.all.dsdsdsdsdxcxdfgfg.value = obj.value;}
}
//处理验证码的js 同密码
function chkyzm(obj) {if (obj.value != '') {var s = md5(md5(obj.value.toUpperCase()).substring(0, 30).toUpperCase() + '13683').substring(0, 30).toUpperCase();document.all.fgfggfdgtyuuyyuuckjg.value = s;} else {document.all.fgfggfdgtyuuyyuuckjg.value = obj.value.toUpperCase();}
}

于是可以把这一段内容用java实现

String xuehao = MD5Encode(id +
MD5Encode(password).substring(0, 30).toUpperCase() + school).toUpperCase().substring(0, 30);String yzm = md5(md5(validate.toUpperCase()).substring(0, 30).toUpperCase() + school)
.substring(0, 30).toUpperCase();

注:Md5加密算法百度一大堆,上述的id为 学号字段,password为前台传入的密码字段,school为学校的编号,validate为我们解析成功后的验证码

这里说到验证码,因为我们模拟登陆即要进行机器识别验证码,java的ocr我试过 识别率太低,于是接入了百度AI识别,虽然有次数限制,但是识别率还是比较高。
一番周折之后,可以进行框架搭建和逻辑编写了

识别验证码

我们用的python写的深度识别
这里暂不说这个,申请完之后会拿到一个appid和appkey,secretkey,后续验证码识别会用到
通过教务系统拿到登录系统的验证码地址
即验证码地址

从chrome打开会是一段乱码,不需要管。
我们直接开始模拟爬取该地址然后进行识别:

 public static List getImage() {//获取该地址String url = validateUrl+System.currentTimeMillis()%1000;try {HttpResponse response = HttpUtil.createGet(url).header("Accept","image/webp,image/apng,image/*,*/*;q=0.8").header("Accept-Encoding", "gzip, deflate").header("Accept-Language","zh-CN,zh;q=0.9").header("Connection","keep-alive")//host/refer 即该教务处的host ...因为是模拟登录,所以要模拟的像一些.header("Host",Constant.HOST).header("Referer", Constant.LOGIN_URL).header("User-Agent",Constant.USER_AGENT).execute();InputStream in = response.bodyStream();long time = System.currentTimeMillis();//这里拿到输入流之后进行读取 然后图片下载下来String filePath = CommonLog.CACHE_MAP.get("filePath")+ time+".jpg";OutputStream out = new FileOutputStream(filePath);byte b[] = new byte[1024 * 8];int len = 0;while ((len = in.read(b)) != -1) {out.write(b, 0, len);}System.out.println("1:>>>"+response.getCookieStr());System.out.println(Base64Encoder.encode(filePath));List list = Lists.newArrayList();//下载下来之后 进行验证 即getValidatelist.add(response.getCookies().get(0));String validateCode = getValidate(filePath,0);list.add(validateCode);return list;} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}

识别图片

 public static String getValidate(String filePath,int j){String url = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic";byte[] imgData = new byte[0];try {imgData = FileUtil.readFileByBytes(filePath);String imgStr = Base64Util.encode(imgData);String imgParam = URLEncoder.encode(imgStr, "UTF-8");String param = "&image=" + imgParam;try {String result = top.choviwu.toolkit.sort.util.HttpUtil.post(url, getAuth(), param);JSONObject jsonObject = new JSONObject(result);JSONArray jsonArray = jsonObject.getJSONArray("words_result");StringBuilder stringBuilder = new StringBuilder();for (int i = 0; i < jsonArray.length(); i++) {JSONObject json = jsonArray.getJSONObject(i);stringBuilder.append(json.get("words"));}String ret = stringBuilder.toString();
//                while ((StringUtils.isBlank(stringBuilder.toString()) || stringBuilder.toString().length()!=4)&& j <= 5) {//                    getValidate(filePath, j++);
//                }return StringUtils.replace(ret, " ", "");} catch (Exception e) {e.printStackTrace();}} catch (IOException e) {e.printStackTrace();}return "";}

模拟登录

   public static HttpCookie login(String id, String password,String school) {//获取验证码List list = ValidateImage.getImage();HttpCookie cookie = ((HttpCookie) list.get(0));String validate = (String) list.get(1);String xuehao = MD5Encode(id + MD5Encode(password).substring(0, 30).toUpperCase() + school).toUpperCase().substring(0, 30);String yzm = md5(md5(validate.toUpperCase()).substring(0, 30).toUpperCase() + school).substring(0, 30).toUpperCase();HttpResponse response = HttpUtil.createPost(url).form(map).form("dsdsdsdsdxcxdfgfg", xuehao).form("fgfggfdgtyuuyyuuckjg", yzm).form("__VIEWSTATE", getViewState()).form("txt_asmcdefsddsd", id).header("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9").header("Content-Type", "application/x-www-form-urlencoded").header("Host", "www.xacxxy.com:88").header("Origin", "http://www.xacxxy.com:88").header("Referer", "http://www.xacxxy.com:88/jwweb/_data/index_LOGIN.aspx").header("Upgrade-Insecure-Requests", "1").header("User-Agent", Constant.USER_AGENT).header("Cookie", cookie.toString()).execute();//学号密码加密 然后再通过表单提交的方式提交 得到相应数据String body = response.body();if (body.contains(Constant.VALIDATE_ERROR)) {login(id, password,school);} else if (body.contains("帐号或密码不正确")) {throw new CrudException(ExceptionEnum.account_or_password_error);}System.out.println("2:>>>" + cookie);//成功返回cookiereturn cookie;}

登录成功之后就好办了,直接可以获取该成绩
拿到该成绩的接口地址 jwweb/xscj/Stu_MyScore_rpt.aspx

可以看出来这个jsp是成绩的渲染师徒视图,后面获取到成绩之和就解析该table


这里我们拿成绩分布的接口,为什么呢?因为查看成绩的接口后台是返回一张图片的,这样的话又要二次解析图片,反而很麻烦,这个接口可以直接通过table的解析来获取结果
于是开始爬该地址,

爬成绩接口

拿到上一个的cookie数据,然后请求上面说的那个接口
说一下这里面的参数,这里面需要传学期和学年的参数,
即2020学年第一学期传202001 学年则传2020

    public static List<CourseScore> getCourseScores(HttpCookie cookies, String xnxq, String xn) {List<CourseScore> courseScores = Lists.newArrayList();try {//上面传个20201  这里会解析学期的参数的String xq = xnxq.substring(xnxq.length() - 1);HttpResponse response = HttpUtil.createPost("http://host/jwweb/xscj/Stu_cjfb_rpt.aspx").header("Accept", "image/webp,image/apng,image/*,*/*;q=0.8").header("Content-Type", "application/x-www-form-urlencoded").header("Host", "host").header("Referer", "http://host/jwweb/xscj/Stu_cjfb.aspx").header("Upgrade-Insecure-Requests", "1").header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36").header("Cookie", cookies.toString()).cookie(cookies.toString()).form("sel_xn", xn).form("sel_xq", xq).form("SelXNXQ", Integer.valueOf(xq) + 1).form("submit","").execute();System.out.println(response.body());//拿到数据进行解析table元素,遍历成绩Elements elements = Jsoup.parse(response.body()).children();Elements scores = elements.get(0).children().get(1).children().get(0).children().get(1).getElementsByTag("tr");for (int i = 0; i < scores.size(); i++) {if(i>=scores.size()-2){return courseScores;}Elements childrens = scores.get(i).children();String course = childrens.get(1).text();String score = childrens.last().text();CourseScore courseScore = new CourseScore();courseScore.setAddtime(new BigDecimal(System.currentTimeMillis())).setCourseCredit(Double.valueOf(childrens.get(2).text())).setCourseName(course).setCourseType(childrens.get(3).text()).setNatureRead(childrens.get(5).text()).setScore(Double.valueOf(score)).setTestType(childrens.get(4).text()).setXnxq(xnxq);courseScores.add(courseScore);}return courseScores;}catch (Exception e){e.printStackTrace();}finally {return courseScores;}}

上面为后端的逻辑

前端逻辑就不展示了,都是一些html

主要是说了一下这个的思想
登录完成之后会重定向到获取成绩页,这里其实是绕过了验证码登录的哪一步


这里我统一返回了Json结构,方便解析

到这里就贴完了,如果有看不懂的可以私聊我QQ:QQ
或者我的博客博客

代码我丢到了github上,需要的可自行去debug 仓库
clone下代码之后需要切换到dev分支

https://github.com/planetRun/qingguo-spider

本篇为原创,转载须注明来源,否则后果自负

青果教务处系统爬虫(java)相关推荐

  1. 拟物校园 | 拟物校园,一个高校教务系统爬虫,现支持正方教务、青果教务。

    特别声明:除非注明,否则均为 夏末浅笑博客 原创文章,禁止任何形式转载 nivinEdu 拟物教务,一个高校教务系统爬虫 github:https://github.com/nivin-studio/ ...

  2. 大型网站系统与Java中间件实践

    大型网站系统与Java中间件实践(贯通分布式高并发高数据高访问量网站架构与实现之权威著作,九大一线互联网公司CTO联合推荐) 曾宪杰 著   ISBN 978-7-121-22761-5 2014年4 ...

  3. python实现高校教务管理系统_Python实现新版正方教务系统爬虫

    目录~ 引入 需要什么软件? 模拟登陆 代码实现(登陆) 模拟获取成绩 代码实现(获取成绩) 解析成绩 测试(完成图) 作者的话 引入 就在我刚刚写完旧版正方系统爬虫的时候(旧版正方系统爬虫代码) 学 ...

  4. 新版方正教务系统爬虫

    新版方正教务系统爬虫 技术 解释 Python 2.7 BeautifulSoup 4.X Pycharm 2017 Firefox - Firebug - 新版教务处地址 218.199.228.4 ...

  5. 湖南工业大学教务系统爬虫(模拟登陆篇)

    湖南工业大学教务系统爬虫(模拟登陆篇) 之前写了一个教务系统的爬虫程序,可以根据用户要求爬取任何一部分的数据,也可以模拟提交数据,可能这也是部分工大计算机学生比较感兴趣的,所以今天就在这分享一下整个的 ...

  6. apt安装JDK8并设置为系统默认Java

    更多文章请点击 文章目录 1. 背景 2. apt安装jdk8 2.1 搜索jdk8安装包 2.2. 安装选定版本 2.3. 更改系统首选java版本 3. 总结 1. 背景 最近重装系统,新系统自带 ...

  7. 视频教程-大数据Java强化班(十)之大数据爬虫-Java

    大数据Java强化班(十)之大数据爬虫 10年一线开发及项目管理经验,6年以上大数据项目架构.实施.开发与运维经验,骨灰级大数据玩家,对Hadoop.Storm.Spark.Flink.Kylin.D ...

  8. 作为初学者,应该如何系统学习Java呢?

    Java编程语言发展的迅猛,每年的Java人才缺口人数都高达百万以上.作为IT小白应该如何系统学习Java呢?作为过来人,小千在这里给大家一些中肯的意见,希望对大家的工作和学习Java有一定的借鉴作用 ...

  9. cc java开发环境搭建_Windows系统下java开发环境搭建

    总的来说,开发环境是程序员工作的基础,没了他,IT工作就没得开展了.话不多说,今天提供的教程是Windows系统下Java开发环境的搭建,具体如下 1.下载并安装JDK(JAVA Developmen ...

  10. 系统学习 Java IO (六)----管道流 PipedInputStream/PipedOutputStream

    目录:系统学习 Java IO---- 目录,概览 PipedInputStream 类使得可以作为字节流读取管道的内容. 管道是同一 JVM 内的线程之间的通信通道. 使用两个已连接的管道流时,要为 ...

最新文章

  1. Ubuntu系统创建AndroidStudio启动图标(快捷方式)
  2. boost::typeof模块实现函数绑定的测试程序
  3. libcurl实现解析(3) - libcurl对select的使用
  4. vs2008网站模式下不能设置rdlc的数据源
  5. LinuxCentos7 防火墙开放端口,查看状态,查看开放端口
  6. 原生JS封装运动框架。
  7. tensorflow之pd模型
  8. java中ant是干什么的_Java_Ant详解(转载)
  9. java中的url进行编码和解码
  10. 光谱共焦的测量原理及厚度测量模式
  11. 预演:使用 TensorFlow 进行深度学习
  12. 2021年金属非金属矿山(地下矿山)安全管理人员最新解析及金属非金属矿山(地下矿山)安全管理人员证考试
  13. 西瓜书读书笔记(一)
  14. 如何在PS中为图片添加塑料布效果
  15. SpringBoot企业微信点餐系统
  16. 阳历日期转阴历工具类
  17. 参加《全流程全要素的研发项目管理》培训记录与心得
  18. 游戏多开计算机内存不足,技术宅 解决天刀多开单开内存不足问题
  19. 使用FastJson进行驼峰下划线相互转换写法及误区
  20. 第十届蓝桥杯C语言B组题解

热门文章

  1. 【所见即所得】数据分析最有用的25个 Matplotlib图【附代码】
  2. Win10环境下 Cad插件使用失败 解决方法
  3. python中day_python day02
  4. 支付宝VS微信,谁在抄袭谁?
  5. JAVA长方形正方形_正方形不是长方形的终极解决办法
  6. 【业务人员第一视角】氚云低代码开发平台测评
  7. 【电脑运用及修理】6套台式组装机电脑配置清单大全(2022年618)
  8. S3C64xx设备树支持
  9. 逻辑学中的思维规律:同一律,不矛盾律,排中律,充足理由律
  10. java谷歌翻译_Java 调用 google 翻译