MOOC网课爬虫逆向(二)
补充一下关于开小号的问题,事实上对于我的mooc线代课,你开小号只能通过分数知道错了几个,但是不能知道哪个错了以及正确答案是多少——我将它理解为防止别人开小号
那你暴力开小号去硬排列组合,我可以很负责的告诉你,第一周的测试有50道题,你这样去排列组合,你孙子都得不到答案,这就是爬虫的必要性,而且不能无脑爬,用啥啥selenium大法好行不通
而且事实上,所有可以用selenium的都可以用请求来解决,而且更快
1.1开个小号,不然抓包不小心就提交了
1.2Burpsuite抓包
1.2.1整体分析
抓什么包其实很讲究的,
按下开始测试的按钮后,就会直接跳题出来
这里按F12打开浏览器开发者选项
直接暂停了,没关系,点这个,然后刷新一下页面就可以,断点就不会端下来了
这里先说一下为什么直接抓包,不看看源代码,这个你可以自己试试,源代码经过了混淆,真的我不想解密了
如果真的有人想要看看如何解密的话,可以参考我的另一篇文章https://zhuanlan.zhihu.com/p/545539451 链接: 知乎链接
为啥是知乎呢?因为那篇文章csdn审核没过,也是关于爬虫的。。。。
然后你看看开发者工具的网络中,看看按下提交后有啥请求
ok三个请求,现在能看就看看呗
1.2.2提交后请求的分析
1.2.2.1mocQuizRpcBean.submitAnswers
载荷和回答如上
这个回答没什么好说的,看下值是啥样的,可以留着之后作爬虫请求是否成功的验证
着重看下载荷:
{
"paperDto": {
"tid": 1241562141,
"tname": "测验1",
"aid": 2719632665,
"submitStatus": 1,
"type": 2,
"objectiveQList": [
], //这里我删了点东西
"subjectiveQList": [],
"questions": null,
"answers": null,
"evaluateVo": null,
"showAnalysis": false,
"autoSubmit": false,
"allowSwitchPageCount": -1,
"switchPageCount": 0,
"submitType": 1,
"deviceType": null,
"examId": -1,
"name": null,
"submitCount": null,
"deadline": null,
"totalScore": null,
"subjectiveTotalScore": null,
"objectiveTotalScore": null,
"subjectiveScore": null,
"objectiveScore": null,
"evaluateJudgeType": null,
"evaluateNeedTrain": null,
"evaluateStart": null,
"evaluateEnd": null,
"answererId": 1029744437,
"analyseEnable": null,
"scoreReleaseTime": null,
"examTime": null,
"startTime": 1666781339872,
"submitTime": null,
"tryTime": 3,
"usedTryCount": 102,
"ip": null,
"isCorrectSubject": null,
"scoreReleaseType": null,
"examType": null,
"memberId": null,
"nickname": null,
"realName": null,
"studentNumber": null
},
"preview": false
}
对没错我删减了点东西,删了什么呢?
这是个列表,里面是题目,有十个,我就拿其中一个来看
{
"id": 3321780599,
"gmtCreate": null,
"gmtModified": null,
"stdAnswer": null,
"examId": null,
"testId": null,
"type": 1,
"fillblankType": null,
"score": 1,
"options": null,
"position": 1,
"allowUpload": null,
"title": "<p>‎<span style=\"font-family:宋体;\" >齐次线性方程组</span><img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_6e5cb362-e158-481a-8744-46083c6e756b.png\" /><span style=\"font-family:宋体;\" ></span><span style=\"font-family:宋体;\" >有非零解的充分必要条件是( ).</span></p>‌<p>‎<br ></p>‌",
"plainTextTitle": "齐次线性方程组【图片】有非零解的充分必要条件是( ).",
"titleAttachment": null,
"description": null,
"sampleAnswerJson": null,
"judgerules": null,
"analyse": null,
"optionDtos": [{
"id": 84162913447,
"content": "<p><img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_ff50a986-ff0f-46bb-8005-d1db463201ec.png\" /></p>",
"answer": null,
"analyse": null,
"selectCount": null
}, {
"id": 384162913447,
"content": "<p><span style=\"font-size:14px;font-family:'Calibri',sans-serif;\" ><img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_c22b0038-1854-42fb-adf5-efe53204123a.png\" /></span><span style=\"font-size:14px;font-family:宋体;\" >且<img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_643d5964-4b87-4a74-ac56-ae5c0dc743d9.png\" /></span></p>",
"answer": null,
"analyse": null,
"selectCount": null
}, {
"id": 284162913447,
"content": "<p><span style=\"font-size:14px;font-family:'Calibri',sans-serif;\" ><img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_8f1c6639-4bc2-4b4d-abff-1f7fab7650c3.png\" /></span><span style=\"font-size:14px;font-family: 宋体;\" >或<img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_d606e641-5697-44ae-af49-8fb25fc35ce6.png\" /></span></p>",
"answer": null,
"analyse": null,
"selectCount": null
}, {
"id": 184162913447,
"content": "<p><img src=\"https://edu-image.nosdn.127.net/_PhotoUploadUtils_dcd83fd2-b610-454a-91a1-56c7a2938555.png\" /></p>",
"answer": null,
"analyse": null,
"selectCount": null
}],
"judgeDtos": null,
"sampleAnswers": null,
"titleAttachmentDtos": null,
"ojTimeLimit": null,
"ojMemLimit": null,
"ojSupportedLanguage": null,
"ojNeedInput": null,
"ojSupportedLanguageList": null,
"ojTryTime": null,
"ojCases": null,
"correctNumber": null,
"totalScore": null,
"correctRate": null,
"avgScore": null,
"mocQuestionTagDto": null,
"canEdit": null,
"edsQuestionId": null,
"isOptionRandom": null,
"optionNumber": null,
"submitCount": null
}
这里就不让你们猜意思了
首先是整个大的字典里:
tid:用来区分哪次测验的,每个测验都不同,比如第一周测验和第二周测验
就不同,但是第一周的测验下不同提交相同
aid:每次测验的都不同,对于每次进行的测试,这是唯一的!
暂停一下,为什么是唯一的呢?这就是很玄幻的一个地方了。
尝试更改,让它+1
!!!发现了什么?没错,我们来到了另一个次元,这完全不是线代课程那次检测的!
其实每个人每次的提交都是靠这个aid区分的!
那意味着什么?
1.我可以通过aid跳跃次元,跃迁题目
2.别人正在做的时候,得知他的aid,可以直接“帮”他提交!让他零分!
当然这不提倡,这需要一定的社会心理学知识,我们要共同富裕才行,而且你会碰到一个无法避免的问题——这里是看以往测验记录里通过改aid来实现跃迁的,只能看,不能改!
那细心的人可能已经看到之前我贴的那图里居然有答案?那可不可以通过这种方法找到答案呢?巧合罢了,老实说我都没想到原aid+1会出现这个。。。。。其实线代的aid输进去,是不会有答案的。
路已经断了?别急,这次第一个请求,虽然的确是最重要的一个
1.2.2.2mocQuizRpcBean.getQuizInfo
载荷和回答如下:
{
"code": 0,
"result": {
"tid": 1241562141,
"aid": 2719632665,
"termId": 1468219449,
"targetAnswerform": {
"id": 2719632665,
"tid": 1241562141,
"aid": 2719632665,
"subjectAid": null,
"submitTime": 1666782061667,
"score": 0.00,
"effectStatus": 0,
"answererId": 1029744437,
"name": null,
"type": 2,
"testId": 1241562141,
"examId": -1,
"totalScore": 10.0,
"finalScore": 0.0,
"objectiveScore": 0.0,
"subjectiveScore": null,
"objectiveTotalScore": null,
"subjectiveTotalScore": null,
"subjectTestId": null,
"extraScore": null,
"effectiveScorePlusExtra": null,
"deadline": null,
"email": null,
"nickname": null,
"studentNumber": null,
"mocAuthenticatedMemberDto": null,
"scorePubStatus": null,
"draftSubjectiveBonusScore": null,
"reviewStatus": null,
"draftSubjConfirmed": null,
"subMocAnswerForms": null,
"evaluates": null,
"aggreId": null,
"aggreScore": null,
"showScore": true,
"groupName": null,
"submitType": 1,
"correctNumber": null
},
"startTime": null,
"lastModifiedTime": null,
"deadline": 1672587000000,
"lastSubmitTime": -1,
"duration": 3600,
"effectScore": 0,
"userScore": null,
"totalScore": 10.0,
"totalTryCount": 3,
"usedTryCount": 102,
"examScorePubStatus": null,
"scorePubStatus": null,
"effectScoreRule": 2,
"description": "",
"name": "测验1",
"evaluateScoreReleaseTime": null,
"ansformInfoList": null,
"questionCount": 10,
"bonusScore": null,
"analyseSetting": 1,
"showAnalysis": false,
"needFillMemberDetailInfo": null,
"allowSwitchPageCount": -1,
"tryTime": null,
"examTime": null,
"scoreReleaseTime": null,
"scoreReleaseType": null,
"evaluateJudgeType": null,
"evaluateStart": null,
"evaluateEnd": null,
"objectTestId": null,
"subjectTestId": null,
"taskStatus": null,
"examType": null
},
"message": "",
"traceId": "",
"sampled": false
}
那这里的aid和tid是和上面那个请求对应的,很好理解
再看载荷和回答
载荷就是把之前第一个请求的载荷parpedto字典的大部分给传进去
响应就是也是返回了大部分原来的东西,其实没啥变化好吧。
好了都分析了一遍了,感觉没啥重要的东西,咋办啊?
难道之前的csrfKey是关键?
当然不是啦,之前我们就改了改aid就实现次元跃迁了,这个csrfKey会有用吗?
那怎么办?