您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
发送包含指定的数据的HTTP POST,用以模拟单次点击。
// ==UserScript== // @name ZJSU抢课小棉袄 // @namespace https://github.com/Zzzcy-tx/ZJSU_GetMyCoursePLZ // @version 2.31 // @description 发送包含指定的数据的HTTP POST,用以模拟单次点击。 // @author Zzzcy // @match */jwglxt/*gnmkdm=N253512* // @icon https://jwxt.zjgsu.edu.cn/jwglxt/logo/favicon.ico?t=1725699891340 // @grant unsafeWindow // @license MPL // ==/UserScript== var data1, route, responseData; let draggableBox; const qqNumber = '552241992' let shouldCaptureFetch = false; const open = XMLHttpRequest.prototype.open; const send = XMLHttpRequest.prototype.send; const originalSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.open = function (method, url) { //console.log(`yicibuhuo,method=${method}, data=${data}`) console.log(url, method); if (shouldCaptureFetch) { const parser = document.createElement('a'); parser.href = url; //stuNumber = url.substring(58,69); //console.log(stuNumber); } return open.apply(this, arguments); }; XMLHttpRequest.prototype.send = function (data) { console.log(data); if (shouldCaptureFetch) { data1 = data; } console.log(data1); originalSend.call(this, data); }; const footer = document.getElementById('footerID'); const resultDiv = document.createElement('div'); resultDiv.textContent = ' 等待开启。'; resultDiv.style.textAlign = 'center'; resultDiv.style.fontFamily = 'Arial'; resultDiv.style.fontWeight = 'bold'; resultDiv.style.fontSize = '20px'; resultDiv.style.marginTop = '20px'; resultDiv.style.marginBottom = '20px'; footer.insertAdjacentElement('beforebegin', resultDiv); const buttonContainer = document.createElement('div'); buttonContainer.style.display = 'flex'; buttonContainer.style.justifyContent = 'center'; buttonContainer.style.gap = '40px'; buttonContainer.style.marginTop = '20px'; buttonContainer.style.marginBottom = '20px'; buttonContainer.style.textAlign = 'center'; buttonContainer.style.fontFamily = 'Arial'; buttonContainer.style.fontSize = '18px'; // 创建发送 POST 请求按钮 const requestButton = document.createElement('button'); requestButton.style.padding = '5px 15px'; requestButton.textContent = '开始模拟点击'; buttonContainer.appendChild(requestButton); // 将按钮添加到容器中 // 创建停止按钮 const stopButton = document.createElement('button'); stopButton.style.padding = '5px 15px'; stopButton.textContent = '停止模拟点击'; buttonContainer.appendChild(stopButton); // 将按钮添加到容器中 // 创建录制 POST 按钮 const recordButton = document.createElement('button'); recordButton.style.padding = '5px 15px'; recordButton.textContent = '录制点击数据'; buttonContainer.appendChild(recordButton); // 将按钮添加到容器中 // 将按钮容器插入到 footer 之前 footer.insertAdjacentElement('beforebegin', buttonContainer); let isRequesting = false; requestButton.addEventListener('click', () => { if (!isRequesting) { isRequesting = true; requestLoop(); } }); stopButton.addEventListener('click', () => { isRequesting = false; resultDiv.textContent = '等待开启。' }); recordButton.addEventListener('click', () => { if(shouldCaptureFetch){ shouldCaptureFetch = false resultDiv.textContent = '未开始监听POST' } else { shouldCaptureFetch = true resultDiv.textContent = '正在监听POST……' } }); async function sendPostRequest() { try { const data = data1; let xhr = new XMLHttpRequest(); xhr.withCredentials = true; xhr.open('POST', `https://jwxt.zjgsu.edu.cn/jwglxt/xsxk/zzxkyzb_xkBcZyZzxkYzb.html?gnmkdm=N253512`); xhr.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/117.0'); xhr.setRequestHeader('Accept', 'application/json, text/javascript, */*; q=0.01'); xhr.setRequestHeader('Accept-Language', 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2'); xhr.setRequestHeader('Accept-Encoding', 'gzip, deflate, br'); xhr.setRequestHeader('Referer', `https://jwxt.zjgsu.edu.cn/jwglxt/xsxk/zzxkyzb_cxZzxkYzbIndex.html?gnmkdm=N253512&layout=default`); xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8'); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.setRequestHeader('Origin', 'http://jwxt.zjgsu.edu.cn'); xhr.setRequestHeader('DNT', '1'); xhr.setRequestHeader('Connection', 'keep-alive'); xhr.setRequestHeader('Cookie', `${route}`); xhr.setRequestHeader('Sec-Fetch-Dest', 'empty'); xhr.setRequestHeader('Sec-Fetch-Mode', 'cors'); xhr.setRequestHeader('Sec-Fetch-Site', 'same-origin'); xhr.onload = await function() { responseData = xhr.response; console.log(xhr.response); }; await xhr.send(data); var flag = JSON.parse(responseData).flag; console.log(flag); if(flag === '-1'){ resultDiv.textContent = '正在等待余量放出,请耐心等待……' } else if( flag === '0' ){ resultDiv.textContent = '排课时间冲突或未正确录制点击数据!请刷新界面' } else if( flag === '1' ){ resultDiv.textContent = '恭喜,抢课成功! \\^_^// ' } else { resultDiv.textContent = `未知错误,请联系技术人员QQ:${qqNumber}` } //resultDiv.textContent = JSON.stringify(responseData, null, 2); // 如果data.flag等于1,或者停止按钮按下,则停止请求 if (flag === '1' || flag === '0' || !isRequesting) { isRequesting = false; } } catch (error) { console.error('发生错误:', error); } }; async function requestLoop() { while (isRequesting) { await sendPostRequest(); await sleep(1000); route = document.cookie; } }; function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }; //提示界面 (function () { const style = document.createElement('style'); style.textContent = ` .grabclasscontainer { width: 320px; text-align: center; position: fixed; right: 0px; bottom: 0px; height: 350px; border: 2px #333 solid; background-color: #d5e8fc; z-index: 999; } .grabclasscontainer label { flex: 1; text-align: right; margin-right: 10px; } .grabclasscontainer .dragBar { height: 30px; line-height: 30px; background-color: #505860; cursor: move; margin-bottom: 9px; } .grabclasscontainer .content { overflow-y: auto; height: 309px; } .grabclasscontainer .dragBar { height: 30px; line-height: 30px; background-color: #07c160; cursor: move; margin-bottom: 9px; } .grabclasscontainer .copyright { text-align: left; } .grabclasscontainer .graberror { color: #e91a0b; } .grabclasscontainer .grabsuccess { color: #0be94e; } ` document.head.appendChild(style); const grabclasscontainer = document.createElement('div'); grabclasscontainer.className = 'grabclasscontainer'; grabclasscontainer.id = 'grabclasscontainer'; grabclasscontainer.innerHTML = ` <div class="dragBar" id="dragBar"> 按住拖动 </div> <div class="content"> <div class="copyright"> 【使用方式】<br> 1.点开你想要的课,确保这课的时间段没有冲突。<br> 2.滚动到网页最下方,点击“录制点击数据”,然后点右边的“选课”<br> 3.中间会弹出提示“已无余量,不可选”的提示,点确定。<br> 4.接着点击网页最下方的“开始模拟点击”,观察按钮上方提示,“正在等待余量放出,请耐心等待……”则为正常<br> 5.不要关闭网页,不要关闭电脑,最好把网页最大化,等待抢课成功。<br><br><br> 【联系作者】有偿帮助:QQ:${qqNumber}<br> </div> </div> ` document.body.appendChild(grabclasscontainer); draggableBox = document.getElementById("grabclasscontainer"); const dragBar = draggableBox.querySelector(".dragBar"); let isDragging = false; let offsetX, offsetY; dragBar.addEventListener("mousedown", (e) => { isDragging = true; offsetX = e.clientX - draggableBox.getBoundingClientRect().left; offsetY = e.clientY - draggableBox.getBoundingClientRect().top; draggableBox.style.transition = "none"; }); document.addEventListener("mousemove", (e) => { if (!isDragging) return; let x = e.clientX - offsetX; let y = e.clientY - offsetY; draggableBox.style.left = x + "px"; draggableBox.style.top = y + "px"; }); document.addEventListener("mouseup", () => { isDragging = false; draggableBox.style.transition = "all 0.3s ease"; // 添加平滑的过渡效果 }); draggableBox.querySelector('.clear').addEventListener('click', () => { localStorage.removeItem('targetTeacher'); localStorage.removeItem('targetTime'); localStorage.removeItem('firstmenu'); localStorage.removeItem('secondmenu'); }); })();