模拟教务评教(强智教务)—一件评教实现原理
前言
- 前不久,學校有個校園幫助型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
總結
以上是生活随笔為你收集整理的模拟教务评教(强智教务)—一件评教实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: python可视化文本分析(2)—sno
- 下一篇: Dungeon Master(三维bfs
