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

举报
bigsai 发表于 2021/02/03 02:07:28 2021/02/03
【摘要】 前言 前不久,学校有个校园帮助型app某某圈因为一件评教功能被教务批评了。现在有很多查成绩,查课程的app,他们的实现原理到底是啥了。这两天来到发小扬州这边,学习实现了这个功能,并且用java和python都写了一下,但是鉴于web端只会java,最后集成到springboot部署到服务器提供的小服务。以前只知道这些东西是爬虫爬出来的,原本以为非常简单,自己研究了一下...

前言

  • 前不久,学校有个校园帮助型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;
		}
		@Override
		public void run() { // TODO Auto-generated method stub try { judteacher(url, cookies); System.out.println(Thread.currentThread().getName() " jud" url); } catch (IOException e) { // TODO Auto-generated catch block e.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(); }
}



  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176

python版本:

import requests
from bs4 import BeautifulSoup
import re
def judteacher(url,cookiedict): res=requests.get(url,cookies=cookiedict) html=res.text soup=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=0 for button in buttoninput: # print(index,button) if index==0: index+=1 continue elif 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))#得到完整的teacherurl try: 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.cookies cookiedict=requests.utils.dict_from_cookiejar(cookiejar) html=res.text soup=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)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

因为是用java版本试水的,所以加了一些反爬措施,发现教务没啥限制,py版本就简写了。另外,只要把第一个java改成函数式就可以融入ssm或者sb了。前端给个模板即可
在这里插入图片描述
由于时间和天气恶劣,没有写太多具体步骤,如果有兴趣可以一起研究探讨,来年下次再用吧。。?。来年把线程池整进去。
本人比较菜,代码不足之处还请大佬指正。

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

文章来源: bigsai.blog.csdn.net,作者:Big sai,版权归原作者所有,如需转载,请联系作者。

原文链接:bigsai.blog.csdn.net/article/details/86516751

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。