一,前言
本程式無需題庫百分之百正確答題,程式僅供測驗,我會分享思路及程式(程式寫的比較爛但功能已經實作),推薦大家看完思路自己獨立完成一下,我會把文章終點放在思路上,思路也就是結論,但是還有一些問題沒有解決,我會在文章最后列舉出來,希望能一起解決,
本文僅做知識分享,切勿用作商業用途,本人是一個大二業余編程愛好者,文章旨在拋磚引玉希望能結識志同道合的朋友,QQ2742431760,思路及程式如有不足之處歡迎指正,
二,程式運行結果

用到的工具是:HttpCanary 和谷歌瀏覽器手機版
三,思路
為了方便描述我對重要網址進行編號
1,打開網址http://dxs.moe.gov.cn/zx/xy/gxlb/-wszzczl-gxdjlhd.shtml -》進入答題-》
2,獲得二維碼的網址
"https://oauth.u.hep.com.cn/oauth/wxapp/qrcode/5f582dd3683c2e0ae3aaaceerandom=lmDtOozSzjJac3XiRB5GibqW&useSelfWxapp=true&enableFetchPhone=false(回傳下面的二維碼地址) 網址①
二維碼地址 https://node2dpublic.hep.com.cn/wxapp/qrcode/2S9RnG85W.png 網址②
網站監控和二維碼是否被掃描的網址https://oauth.u.hep.com.cn/oauth/wxapp/confirm/qr?random=lmDtOozSzjJac3XiRB5GibqW&useSelfWxapp=true 網址③
引數關系:
lmDtOozSzjJac3XiRB5GibqW和/2S9RnG85W的關系是:
lmDtOozSzjJac3XiRB5GibqW為一個隨機的24位的字串(0-9 a-z A-Z),
2S9RnG85W為訪問二維碼一直監控的地址回傳的一個特定的二維碼檔案名,也就是每個24位隨機字串都對應著一張png格式的二維碼,這個二維碼名稱隨意長短不一,
3,獲得登陸的token,在這個包的回傳值里(只管token無視refresh_token就行)

這個包訪問的網址分析:https://ssxx.univs.cn/cgi-bin/authorize/token/?t=1614522688&uid=6031e31b3405f413462cd581&avatar=https:%2F%2Fnode2d-public.hep.com.cn%2Favatar-6031e31b3405f418062cd581-1613882139925&activity_id=5f71e934bcdbf3a8c3ba5061 網址④
t :t引數也是我沒搞懂的,如果按亂數處理確實可以行得通,可是每20道題他就會隨機出現驗證碼,這個驗證碼是跳不過去的(跳過去服務器會拒絕回傳答題所獲得的分值,下文我會提到驗證碼),每個t引數都對應著特定的驗證碼,所以抓到一套包在用編程語言模擬發送的時候碰到t引數不要修改,
uid :應該是固定的在網址③的回傳值中獲得
avatar :也在網址③的回傳值中獲得 引數名稱叫photo,
activity_id :應該是一個固定值,
注:此后的一切我提到的網址都要加上獲得到的token去訪問,
4,獲得題目的race_code引數的地址:https://ssxx.univs.cn/cgi-bin/race/beginning/?t=1614522688&activity_id=5f71e934bcdbf3a8c3ba5061&mode_id=5f71e934bcdbf3a8c3ba51d5&way=1 網址⑤
至于race_code有啥用下文用到我會解釋,這個網址也有接下來要答的題目的id,race_code個人理解就是20到題目綜合的id,這個網址里我們要獲取race_code以及20道題目的id
5,接下來是對答題時出現的驗證碼的處理了,我們會訪問三個網址,這三個網址只是固定套路請不要變化,(有的同學會感覺驗證碼是隨機出現的,在一開頭就處理有用蠻?答:確實有用,經測驗驗證碼僅與t引數有關只要自己抓到一個t引數的包,只要t引數不變就可以通用,用來解決驗證碼問題)
第一個網址https://ssxx.univs.cn/cgi-bin/base/public/key/?t=1614522688 (個人理解:獲得公鑰,以前從來沒接觸過我也不知道干啥用哈,只是按固定格式操作的)
第二個網址https://ssxx.univs.cn/cgi-bin/save/verification/code/(個人理解:獲得驗證碼)
在用編程語言模擬訪問的時候別把包里的請求資訊拉了,每個t對應都是特定的,包的內容如下的格式
第三個網址:https://ssxx.univs.cn/cgi-bin/check/verification/code/(個人理解:驗證驗證碼是否正確)同樣不要忘了包里的內容,以及要原封不動的發送,僅和t引數有關,
最后需要注意的是 這三個包有過期時間(據我推測應該是三天),如果不能正常運行了請更新一下t引數和這三個包里的資料,
6,進行答題
獲得題目:
https://ssxx.univs.cn/cgi-bin/race/question/?t=1614522690&activity_id=5f71e934bcdbf3a8c3ba5061&question_id=5f71e934bcdbf3a8c3ba52e8&mode_id=5f71e934bcdbf3a8c3ba51d5&way=1
回答問題:
https://ssxx.univs.cn/cgi-bin/race/answer/
題目可以重復提交比如一道題答錯了,再復制他回傳的正確答案重新提交就行了,
引數解釋 :t上面說了,activity_id和mode_id是固定值,question_id為網址⑤中回傳引數中獲得,
需要注意的是回答問題的post請求中有內容別忘記了,他的回傳值就是正確答案的id,好了回圈20次就行了,經測驗每道題目以及答案的id是變化的,也就是說同一道題目以及答案會有不同的id,這只是猜測,我爬取了很多題目id并沒有爬取題目(因為爬取題目比較麻煩偷了個懶哈哈,因此我只能看到id所以猜測他是變化的,大家可以自行檢測)
7,把自己的答案提交給服務器,這也是最后一步了,終于完成了哈,
https://ssxx.univs.cn/cgi-bin/race/finish/
提交的內容就是我們上面獲取到的race_code了
順利完成,
一共就需要發送十一個請求就能實作自動答題,很簡單吧,
碰到的問題不明白的:
1,驗證碼與t引數有關,t引數可以是隨機值除了無法通過驗證碼的請求以及無法把答案提交給服務器其他都能正常,那么能否知道t引數和驗證碼的那三條請求的對應關系,進行自定義,
2,題目和答案的id是否一直在變化,如果一直在變化那么其和什么有關,(例如訪問次數,時間,,,,),
代碼區
我寫的代碼不是很好我也不想整理了,如果對我的思路不太理解可以看看代碼輔助理解一下把【狗頭保命】,程式能跑哈哈哈,個人感覺如果你直接用我的代碼去改的話,還不如自己寫省時省力,切勿用于商業行為, 運行程式時如果一切正常但是無法把答案提交給服務器,也就是自己的分數不增加,那應該就是t引數對應的那三個包過期了,畢竟有效期仿佛是三天,自己再抓一個填上試試

①ChinaStudent
import java.util.concurrent.TimeUnit;
public class ChinaStudent {
public static void main (String[] args) {
//生成24位隨機字串
char[] letters = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
'1','2','3','4','5','6','7','8','9','0'};
MyRandom mr = new MyRandom();
String strrand = mr.random(letters,24);
//獲得回傳資訊
String httpurl = "https://oauth.u.hep.com.cn/oauth/wxapp/qrcode/5f582dd3683c2e0ae3aaacee?random="+ strrand +"&useSelfWxapp=true&enableFetchPhone=false";
HttpClient hc = new HttpClient();
String targeturl = hc.doGet(httpurl,"!");
System.out.print(targeturl);
//處理回傳資訊
String imgurl;
Regex regex = new Regex();
imgurl = regex.regex(targeturl, "https://node2d-public.hep.com.cn/wxapp/qrcode/[\\w]+.png")[0];
//下載二維碼
Download download = new Download();
download.down("F:\\", imgurl);
//一直檢測二維碼是否被掃描
boolean flag = true;
String examinestr = "空";
//需要監控的網址
String examineurl = "https://oauth.u.hep.com.cn/oauth/wxapp/confirm/qr?random="+strrand+"&useSelfWxapp=true";
//生成?t=1614057480型別的字串
String tstr ="1614522690";
String uid;
String photo;
String tokenurl;
String token;
String tokenstr;
String qstr;
String[] str = new String[30];
String[] str2 = new String[30];
String race_code = "";
String[] qid =new String[30];
String wanswer;
String wastr;
String answerurl = "https://ssxx.univs.cn/cgi-bin/race/answer/";
String answerstr;
String[] answer=new String[30];
String str1="";
String str3 = "";
long startTime = 0;
long endTime = 0;
while(flag) {
examinestr = hc.doPost(examineurl,"!","!");
System.out.println(examinestr);
if(!examinestr.contains("500")) {
flag =false;
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
uid = regex.regex(examinestr, "_id\":\"[\\w]+")[0];
str = uid.split("\":\"");
uid = str[1];
photo = regex.regex(examinestr, "photo\":\"[\\S]+?\"")[0];
str = photo.split("\"");
photo = str[2];
tokenurl = "https://ssxx.univs.cn/cgi-bin/authorize/token/?t=" + tstr + "&uid=" + uid + "&avatar=" + photo + "&activity_id=5f71e934bcdbf3a8c3ba5061";
tokenstr = hc.doGet(tokenurl,"!");
token = regex.regex(tokenstr, " \"token\": \"[\\S]+\"")[0];
str = token.split("\"");
token = str[3];
hc.doGet("https://ssxx.univs.cn/cgi-bin/base/public/key/?t="+tstr, token);
while(true) {
startTime = System.currentTimeMillis();
qstr = hc.doGet("https://ssxx.univs.cn/cgi-bin/race/beginning/?t="+tstr+"&activity_id=5f71e934bcdbf3a8c3ba5061&mode_id=5f71e934bcdbf3a8c3ba51d5&way=1",token);
race_code = regex.regex(qstr, "race_code\": \"[\\S]+\"")[0];
str = race_code.split("\"");
race_code = str[2];
qid[0] = regex.regex(qstr, "\\[\"[\\S\\s]*\\]")[0];
str2 = qid[0].split("\"");
for(int i=0;i<20;i++) {
System.out.println("答題第: "+(i+1)+"道");
qid[i] = str2[1+i*2];
String qurl = "https://ssxx.univs.cn/cgi-bin/race/question/?t="+tstr+"&activity_id=5f71e934bcdbf3a8c3ba5061&question_id="+qid[i]+"&mode_id=5f71e934bcdbf3a8c3ba51d5&way=1";
wastr = hc.doGet(qurl, token);
wanswer = regex.regex(wastr, "id\"[\\S\\s]+?\",")[1];
str = wanswer.split("\"");
wanswer = str[2];
str1 = "{\"activity_id\":\"5f71e934bcdbf3a8c3ba5061\",\"question_id\":\""+qid[i]+"\",\"answer\":[\""+wanswer+"\"],\"mode_id\":\"5f71e934bcdbf3a8c3ba51d5\",\"way\":\"1\"}";
answerstr = hc.doPost(answerurl, token,str1);
answer[0] = regex.regex(answerstr, "\\[\"[\\s\\S]+\"]")[0];
if(answerstr.contains("false"))
{
str3 = "{\"activity_id\":\"5f71e934bcdbf3a8c3ba5061\",\"question_id\":\""+qid[i]+"\",\"answer\":"+answer[0]+",\"mode_id\":\"5f71e934bcdbf3a8c3ba51d5\",\"way\":\"1\"}";
hc.doPost(answerurl, token, str3);
}
}
System.out.println(hc.doPost("https://ssxx.univs.cn/cgi-bin/save/verification/code/", token, "{\"activity_id\":\"5f71e934bcdbf3a8c3ba5061\",\"mode_id\":\"5f71e934bcdbf3a8c3ba51d5\",\"way\":\"1\",\"code\":\"e+Zmj8PZZOvDhleZ9llPSVwsq4ehzXRpoGfXucUR+AHltpZwAMO6LoZz3Zly1g0E5wSdybFS1lOpjQoCBMatqQp7jwQFGes5nJ4muiOrUyDm92S75gAP7YQ5TiD2oxpptyACA3MXm+idb8HetZV8FN1pHPIVgDvRUMHBiRLoOis=\"}"));
System.out.println(hc.doPost("https://ssxx.univs.cn/cgi-bin/check/verification/code/", token, "{\"activity_id\":\"5f71e934bcdbf3a8c3ba5061\",\"mode_id\":\"5f71e934bcdbf3a8c3ba51d5\",\"way\":\"1\",\"code\":\"hWQ9JQZedZWpkTWUiACPXr1JiRnuPHEg8Xy64Lj6XwiFCp9rBrmpqDPhxzG2qnBNy7c0mm1DSVnUKMJHfdyEG33UT366lhSMnxJxxZyf19tLMua8u0TUI9Z61xM7qYC1nzbzkMjOmULldJ5LUrsgTh2kA0IoKjbZLJWGYh2nVoU=\"}"));
System.out.println(hc.doPost("https://ssxx.univs.cn/cgi-bin/race/finish/", token, "{\"race_code\":\""+race_code+"\"}"));
endTime = System.currentTimeMillis();
System.out.println("運行時間: "+(endTime-startTime)/1000+"秒");
}
}
}
②Download
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class Download {
public void down(String file,String url) {
InputStream in = null;
String filename;
filename = url.substring(url.lastIndexOf("/")+1);
try {
URL url1 = new URL(url);
URLConnection uc = url1.openConnection();
in = uc.getInputStream();
FileOutputStream out = new FileOutputStream(file + filename);
int j = 0;
while((j = in.read()) != -1) {
out.write(j);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
③HttpClient
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Set;
public class HttpClient {
public String doGet(String httpurl,String token) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;
Set<String> keys;
String cookie = "空";
try {
URL url = new URL(httpurl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
if(!token.contains("!"))
connection.setRequestProperty("Authorization", "Bearer "+token);
//設定連接主機的時間
connection.setConnectTimeout(15000);
//設定讀取遠程回傳的資料時間
connection.setReadTimeout(60000);
connection.connect();
if(connection.getResponseCode() == 200) {
is = connection.getInputStream();
br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
StringBuffer sbf = new StringBuffer();
String temp = null;
while((temp = br.readLine())!= null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
/* Map headers = connection.getHeaderFields();
keys = headers.keySet();
for(String key:keys) {
String val = connection.getHeaderField(key);
System.out.println(key+" "+val);
}*/
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(null != br) {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null!=is) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
connection.disconnect();
}
return result + cookie;
}
public String doPost(String httpurl,String token,String params) {
HttpURLConnection connection = null;
InputStream is = null;
OutputStream os = null;
BufferedReader br = null;
String result = null;
Set<String> keys;
String cookie = "空";
try {
URL url = new URL(httpurl);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type", "application/json");
if(!token.contains("!")) {
connection.setRequestProperty("Authorization", "Bearer "+token);
}
//設定連接主機的時間
connection.setConnectTimeout(15000);
//設定讀取遠程回傳的資料時間
connection.setReadTimeout(60000);
connection.connect();
if(!params.contains("!")) {
OutputStream out = connection.getOutputStream();
out.write(params.getBytes("UTF-8"));
out.flush();
out.close();
}
//添加內容
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String lines;
StringBuffer sbf = new StringBuffer();
while((lines = reader.readLine()) != null) {
lines = new String(lines.getBytes(),"utf-8");
sbf.append(lines);
}
result = sbf.toString();
connection.disconnect();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(null != br) {
try {
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null != is) {
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(null != os) {
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return result;
}
}
④MyRandom
import java.util.Random;
public class MyRandom {
public String random(char[] letters,int j) {
Random random = new Random();
String str = "";
int index = 0;
for(int i=0;i<j;i++) {
index = random.nextInt(letters.length);
str += letters[index];
}
return str;
}
}
⑤Regex
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regex {
public String[] regex(String str,String rex) {
Pattern p;
Matcher m;
String[] strs=new String[100];
int index=0;
p = Pattern.compile(rex);
m = p.matcher(str);
while(m.find()) {
strs[index] = m.group();
index++;
}
return strs;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/266035.html
標籤:其他
上一篇:32課程安排
