前言

  • 前不久,学校有个校园帮助型app某某圈因为一件评教功能被教务批评了。现在有很多查成绩,查课程的app,他们的实现原理到底是啥了。这两天来到发小扬州这边,学习实现了这个功能,并且用java和python都写了一下,但是鉴于web端只会java,最后集成到springboot部署到服务器提供的小服务。
  • 以前只知道这些东西是爬虫爬出来的,原本以为非常简单,自己研究了一下发现还是有很多的坑和坎。大致有一下几点:
  • 模拟登陆,登陆是所有校园app要解决的第一难题,如果没验证码还好,但是如果有验证码解决思路有两个,抓包找图片手动打码,如果会点图像识别可以自己调算法,恰巧咱们科大有个不需要验证码的入口,在官网可以找到。
  • 提交表单问题。在我的测试过程中遇到两点错误,第一就是正确提交表单后发现只提交一个按钮,这个原因是因为他有多个key-value是相同参数,也就是他有提交key-set内容。还有一个是提交可以完整提交但是只是保存没有真正提交,原因是他的js更改参数内容,需要修改,下面会介绍到。
  • 异常处理,提交过的和没提交的表单内容有所不一致,需要进行异常处理保证程序可执行性,
  • 当然写完了还发现一个问题就是速度有点慢的问题,我才发现没用多线程执行,算了算了,反正自己玩玩,就不加了。

步骤

用到的包:
java:jsoup
python:request,re,Beautifulsoup

  • 下面开始介绍攻克的整个步骤(因为账号被测试用完无法给出更多fidder抓包图)

  • 模拟登陆:

  • 这部分算是简单的了,因为以前只是试过一些简单的模拟登陆。但是对一些session和cookie理解不够深刻。导致在这个地方 当时卡了很久。我原本以为是先请求登陆页面->带着这个页面的cookie和页面参数进行登陆->用返回界面的cookie进行操作。这个流程,实际上他第三部不会返回cookie,我当时以为那个地方出问题了 ,用fidder一直找不到问题。其实他将所有信息都存在session中,不过你执行的登陆的操作你的cookie的sessionid这个参数在服务器就是你的身份。

  • 所以,你只需要模拟登陆拿着初始界面的cookie就可以完成所有操作了。根据图片和网页的form结构你可以发现只有两个参数。没有加密或者隐藏参数,直接怼就可以模拟登陆成功。

  • 接着就要根据初始界面找到评教的链接,有实验课评教和理论课评教。然后就是找到各个老师的评教地址,这里他的地址有些不规则,要用正则或者切割获得,爬虫细节不做过多介绍

  • 最后就是进入评教的表单
    我这个是已经评教过的,没评教过的你会发现他有很多隐藏元素,还有就是一个button多个选项你要选一个,并且不能重复一样。就这样我遍历元素提交时候发现几个按钮只有最后一个提交成功,老师评价也成功,经过fidder抓参数和我控制台打印的参数几十个一一对比,发现他不是所有都是key-value,有的是key-set(图中画框的部分),在处理上java需要多加几组data的map,而python自带的字典支持各种形式可以直接用。

  • 就这样,发现所有提交都有效,但是,只是达到保存效果,没有提交。通过抓包再次查看参数。查看原文代码会发现问题所在—js修改参数

  • 这样你就发现问题所在,更改这个参数就可以提交成功。但是,会发现速度不快啊。。。原来忘记把线程池弄进来了。。哎,,算了,不想改代码了,清冷呵呵的。。附上Java和python版本代码:

java(已更新加入线程)

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.Connection.Method;
import org.jsoup.Connection.Response;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;public class moni {public static void main(String[] args) throws IOException {//Scanner sc=new Scanner(System.in);//test test=new test();String url="http://jwgl.just.edu.cn:8080/jsxsd/";Connection con=Jsoup.connect(url).timeout(30000);Response re=con.execute();Document doc=Jsoup.parse(re.body());Elements link=doc.select("form");Elements links=link.select("input");Map map = new HashMap<>();for(Element e:links){if(e.attr("name").equals("USERNAME")) {e.attr("value","162210702210");               }if(e.attr("name").equals("PASSWORD")) {e.attr("value","285511");}if(e.attr("name").length()>0) {map.put(e.attr("name"), e.attr("value"));}            }//登陆部分Connection con2=Jsoup.connect(url "xk/LoginToXk").cookies(re.cookies()).timeout(2000);con2.data(map);con2.followRedirects(true); con2.method(Method.POST);Response re2=con2.execute();System.out.println("succss");//      /*
//       * 登陆成功
//       */String url3=url "xspj/xspj_find.do?Ves632DSdyV=NEW_XSD_JXPJ";Connection con3=Jsoup.connect(url3).timeout(2000);con3.header("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.62 Safari/537.36");con3.header("Connection", "keep-alive");con3.cookies(re.cookies());Response res3=con3.ignoreContentType(true).method(Method.GET).execute();Document doc3=Jsoup.parse(res3.body());Elements elements=doc3.select("td a[href]");String shiyan="http://jwgl.just.edu.cn:8080" elements.get(0).attr("href");String lilun="http://jwgl.just.edu.cn:8080" elements.get(2).attr("href");judgle(shiyan,re.cookies());//实验课理论课评教judgle(lilun,re.cookies());   // System.out.println(shiyan);     }private static void judgle(String url, Map cookies) throws IOException {// TODO 自动生成的方法存根Document doc=Jsoup.connect(url).cookies(cookies).get();Elements elements=doc.select("td a[href]");ExecutorService ex= Executors.newFixedThreadPool(10);int i=0;for(Element e:elements){String judurl=e.attr("href");//javascript:JsMod('/js.................pe=view',1000,700)需要正则匹配//我直接用字符串切割String judur[]=judurl.split("'");judurl="http://jwgl.just.edu.cn:8080" judur[1];try {judThread judThread=new judThread(judurl, cookies);ex.execute(judThread);//judteacher(judurl,cookies);    } catch (Exception e2) {System.out.println(e2);}        }ex.shutdown();}static class judThread implements Runnable{String url;Mapcookies;public judThread(String url,Map map ) {this.url=url;this.cookies=map;}@Overridepublic void run() {// TODO Auto-generated method stubtry {judteacher(url, cookies);System.out.println(Thread.currentThread().getName() " jud" url);} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}private static void judteacher(String judurl, Map cookies) throws IOException {// TODO 自动生成的方法存根Document doc=Jsoup.connect(judurl).cookies(cookies).get();Elements link=doc.select("form");String actionurl="http://jwgl.just.edu.cn:8080" link.attr("action");Elements links=link.select("input");Mapmap=new TreeMap<>();for(Element e:links)//先处理所有隐藏的参数{if(e.attr("type").equals("hidden")){map.put(e.attr("name"),e.attr("value"));}}Elements links2=link.select("#table1 tr");int index=0;//第一个不是参数for(Element e:links2)//处理button类元素{if(index==0) {index ;continue;}else if(index==links2.size()-1){String text=e.select("textarea").first().attr("name");map.put(text, "老师很认真负责!");}else if(index==1) {Elements ele=e.select("input[type=radio]");Element NO2=ele.get(1);map.put(NO2.attr("name"), NO2.attr("value"));//System.out.println(NO2.attr("name"));}else {Elements ele=e.select("input[type=radio]");Element NO1=ele.get(0);map.put(NO1.attr("name"), NO1.attr("value"));//System.out.println(NO1.attr("name"));}index ;//System.out.println(e);}map.put("tj", "提 交");//最后提交form表单for(String a:map.keySet()){System.out.println(a " " map.get(a));}Mapmap2=new HashMap<>();Mapmap3=new HashMap<>();Mapmap4=new HashMap<>();Mapmap5=new HashMap<>();map.put("pj06xh", "1");map2.put("pj06xh", "2");map3.put("pj06xh", "3");map4.put("pj06xh", "4");map5.put("pj06xh", "5");map.put("issubmit", "1");Connection con4=Jsoup.connect(actionurl).cookies(cookies).timeout(2000);con4.data(map).data(map2).data(map3).data(map4).data(map5);con4.referrer(judurl);Response res4=con4.method(Method.POST).execute();}
}

python版本:

import requests
from bs4 import BeautifulSoup
import re
def judteacher(url,cookiedict):res=requests.get(url,cookies=cookiedict)html=res.textsoup=BeautifulSoup(html,'lxml')form=soup.select('form')[0]actionurl='http://jwgl.just.edu.cn:8080'+form.get('action')#需要post提交的表单allinput=form.select('input')dictkey={}for link in allinput:if  not str(link.get('type')).__eq__('button'):dictkey[str(link.get('name'))]=str(link.get('value'))buttoninput=form.select('#table1 tr')index=0for button in buttoninput:# print(index,button)if index==0:index+=1continueelif index==(buttoninput.__len__()-1):text=button.find('textarea').get('name')dictkey[text]='老师很负责任,收益良多'elif index==1:buttonselected=button.select('input[type=radio]')[1]dictkey[str(buttonselected.get('name'))]=str(buttonselected.get('value'))else:buttonselected = button.select('input[type=radio]')[0]dictkey[str(buttonselected.get('name'))] = str(buttonselected.get('value'))index+=1#第0个是没用的,第一个是选满意,剩下非常满意,倒数第一个是文本评论dictkey['tj'] = '提 交'dictkey['pj06xh'] = ["1","2","3","4","5"]dictkey['issubmit']="1"post=requests.post(actionurl,data=dictkey,cookies=cookiedict)print(dictkey)def jud(url,cookiedict):res=requests.get(url,cookies=cookiedict)soup=BeautifulSoup(res.text,'lxml')teachers=soup.select('td a[href]')pattern=re.compile(r'.*[\'](.*)[\'].*')#正则提取javascrit:href='----'for teacherurl in teachers:teacherurl=str(teacherurl.get('href'))m=pattern.search(teacherurl)teacherurl='http://jwgl.just.edu.cn:8080'+str(m.group(1))#得到完整的teacherurltry:judteacher(teacherurl,cookiedict)except Exception as e:print(e)
if __name__ == '__main__':url="http://jwgl.just.edu.cn:8080/jsxsd/"res=requests.get(url)cookiejar=res.cookiescookiedict=requests.utils.dict_from_cookiejar(cookiejar)html=res.textsoup=BeautifulSoup(html,'lxml')data={}inputkey=soup.select("input")for canshu in inputkey:if not str(canshu.get("name")).__eq__(None):data[str(canshu.get('name'))]=canshu.get('value')data['USERNAME']='162210702236'data['PASSWORD']='zhongad3344'#  print(data)urlLogin=url+'xk/LoginToXk'res2=requests.post(urlLogin,data=data,cookies=cookiedict)url3=url+'xspj/xspj_find.do?Ves632DSdyV=NEW_XSD_JXPJ'res3=requests.get(url3,cookies=cookiedict)soup3=BeautifulSoup(res3.text,'lxml')hrefs=soup3.select("td a[href]")shiyan='http://jwgl.just.edu.cn:8080'+str(hrefs[0].get('href'))lilun='http://jwgl.just.edu.cn:8080'+str(hrefs[2].get('href'))jud(lilun,cookiedict)jud(shiyan,cookiedict)

因为是用java版本试水的,所以加了一些反爬措施,发现教务没啥限制,py版本就简写了。另外,只要把第一个java改成函数式就可以融入ssm或者sb了。前端给个模板即可

由于时间和天气恶劣,没有写太多具体步骤,如果有兴趣可以一起研究探讨,来年下次再用吧。。?。来年把线程池整进去。
本人比较菜,代码不足之处还请大佬指正。

如果对后端、爬虫、数据结构算法等感性趣欢迎关注我的个人公众号交流:bigsai

模拟教务评教(强智教务)—一件评教实现原理相关推荐

  1. python3 + selenium 进行强智教务成绩的刷新以及通知成绩(华东理工大学 某ecust)

    强智教务自动刷新教务处成绩,更新后发邮件通知,以某ECUST华理为例子.此处的ECUST华理教务系统是18年9月后的新系统 Windows端或者挂在阿里云上都可以,下文示例是在Ubuntu上运行的. ...

  2. 强智教务系统API学习进度条--(以完结)

    前言 想写一个基于微信公众号的课表及成绩查询系统,记录学习过程与实现. 开发环境 IDEA JDK1.8 强智教务系统API文档 API目录 登录 (以实现) 时间信息 (以实现) 课程信息 成绩信息 ...

  3. python登录教务系统_强智科技教务系统python爬虫模拟登录分析(湖南)

    强智科技教务系统python爬虫模拟登录分析(湖南) 本文章仅用作于学习 前提:最近期末到来,想第一时间看到新出成绩的,于是就有了爬取学校教务系统自己的成绩并通过Qmsg酱推送到自己QQ上的想法,目前 ...

  4. 每日获取强智教务系统课表,并发送短信到学生手机!爬虫真牛逼!

    自从学校换了强智的教务系统后,学校的app的查课表功能基本就报废了,记不住课表的我无奈自己动手. 功能实现:如果当天有课,在当天早上6点30以短信的形式自动发送课表至手机 首先我想的是利用模拟登陆然后 ...

  5. python3 + selenium 强智教务 抢课脚本 #当然是捡漏(是真的劳火(华东理工大学 某ecust(暂时只能抢跨专业、跨年级、公选))

    需提前装好chrome浏览器,python3,selenium等库,以及chromedriver,详细教程请自行百度!! 代码 # -*- coding: utf-8 -*-from selenium ...

  6. 强智教务系统——获取课表

    两个接口: 获取个人信息以及登录成功后header中的token: http://jwxt.xxx.edu.cn/app.do?method=authUser&xh={$学号}&pwd ...

  7. 广金强智教务系统模拟登录

    文章目录 网站首页 表单提交 java实现加密 验证结果 验证码问题 登录请求 网站首页 表单提交 f12查看提交发现有encodeInp()加密字符串 java实现加密 conwork.js var ...

  8. python爬虫获取强智科技教务系统学科成绩(模拟登录+成绩获取)

    python爬取强智科技教务系统,以江苏科技大学为例:本人开发的系统作为参考:https://www.wjn1996.cn/estudy/tools/educationLogin.jsp?school ...

  9. python实现强智科技教务系统抢课(两种方法)

    前言 又到了选课的时间,又一次被教务系统的预选给安排了,硬是一门都没选中.于是想实现有没有自动捡课的方法.就整体分为两种方法,一种是获取get请求然后由python多线程提交去选课,一种是利用自动化测 ...

最新文章

  1. oracle 查看表是否被锁
  2. 小程序开发接口,微信公众平台开发地址
  3. 3、Eternal框架-控制器
  4. 前端学习(2019)vue之电商管理系统电商系统处理attr参数
  5. Can‘t connect to MySQL server on ‘localhost‘(10061)【SQLyog】
  6. Leetcode-952 Largest Component Size by Common Factor(按公因数计算最大组件大小)
  7. mysql 命令行执行存储过程_mysql 命令行执行存储过程
  8. Ubuntu下使用VI编辑文件必知的常用命令
  9. jsp高校科研管理系统servlet设计
  10. 澳洲计算机设计专业大学排名,澳洲设计专业大学排名TOP5
  11. 华三服务器如何修改默认ip,H3C路由器默认登录入口 192.168.124.1 设置步骤
  12. C++ 十进制转换为十六进制 ,十进制转换为二进制,十六进制转换为十进制
  13. SSM | Spring
  14. TaHomA:一套让你在iPad上控制房子,将其变身智能房屋的神奇系统
  15. ECharts地图使用
  16. NOJ ACM-ICPC Scoring
  17. 初识c语言day05(100的阶乘和输出补码)
  18. rabbitmq java 重连_RabbitMQ Java客户端自动重新连接
  19. 报错 | SyntaxError: Legacy octal literals are not allowed in strict
  20. NovalIDE自动补全插件介绍。

热门文章

  1. 编译Bitcoin BCH configure: error: libdb_cxx headers missing ,终于解决了
  2. buu [GXYCTF2019]CheckIn
  3. 修改数据,如何将原数据带到输入框
  4. 2020-11-1(xml)
  5. C++11 运行时变量类型判断
  6. C++用FindFirstFile、FindNext递归遍历硬盘的文件
  7. 线程池之工作项,等待项,计时项 (存在疑问???)
  8. 11、MySQL算术运算符
  9. 1.11 Java数组填充(fill())
  10. 1.9 Java转换流:InputStreamReader和OutputStreamWriter