一.环境部署
我们这里使用简单点的部署方式,首先,我们现在本地电脑上安装“phpstudy_pro”这个软件,软件下载地址放在下面了,软件安装就不做多赘述了
小皮面板,让天下没有难配的服务器环境https://www.xp.cn/
在该软件中,安装Apache Web 服务,MySQL 数据库等服务,启动该服务,并在数据库中导入或创建该数据
当然,你也可以自己安装这些服务,或者使用其它类似的软件来安装该服务
具体安装教程可以参考下面这篇文章
创建数据库和表
/*
SQLyog Ultimate v11.24 (32 bit)
MySQL - 8.0.35-0ubuntu0.20.04.1 : Database - questionbank
*********************************************************************
*/
/*!40101 SET NAMES utf8 */;
/*!40101 SET SQL_MODE=''*/;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`questionbank` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `questionbank`;
/*Table structure for table `topiccollection` */
DROP TABLE IF EXISTS `topiccollection`;
CREATE TABLE `topiccollection` (
`ID` int NOT NULL AUTO_INCREMENT,
`QuestionNo` tinytext NOT NULL,
`Answer` tinytext NOT NULL,
`Type` int NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=8555 DEFAULT CHARSET=utf8mb3;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
导入数据库后,我们需要开始编写对应的后台API了,这个脚本最基础的功能有一下几个API
1.获取题目答案2.提交未记录的答案
在这个例子中,我将使用PHP作为后台API语言,下面是这两个API的关键代码
获取题目答案API示例
//解析传入的参数
$arrID = explode(";", $id);
//返回结果
$dataResult = "";
foreach ($arrID as $id) {
if (!($id == "" || $id == " ")) {
// 在数据库中拿数据作比较
$sql = "SELECT * FROM topiccollection WHERE QuestionNo like '$id'";
$result = mysqli_query($con, $sql);
if ($info = mysqli_fetch_array($result)) {
$answer = $info["Answer"];
$dataResult .= $answer;
} else {
$dataResult .= "-1";
}
$dataResult .= ";";
}
}
echo $dataResult;
新增为记录的题库API示例
<?php
//允许跨站请求
header("Access-Control-Allow-Origin:*");
$id = $_POST['id'];
//导入数据库链接
include("conn.php");
//解析传入的参数
$arrID = explode(";",$id);
foreach($arrID as $temp){
$tempArr = explode("|", $temp);
$questionNo = $tempArr[0];
$answer = $tempArr[1];
if(!($questionNo == "" || $answer == "")){
$sql_1 = "SELECT * FROM topiccollection WHERE QuestionNo LIKE ?";
$stmt_1 = mysqli_prepare($con, $sql_1);
mysqli_stmt_bind_param($stmt_1, "s", $questionNo);
mysqli_stmt_execute($stmt_1);
$result = mysqli_stmt_get_result($stmt_1);
if (!($info = mysqli_fetch_array($result))) {
if (strlen($answer) > 2) {
$type = 1;
} else {
$type = -1;
}
$sql = "INSERT INTO topiccollection(QuestionNo, Answer, Type) VALUES (?, ?, ?)";
$stmt = mysqli_prepare($con, $sql);
mysqli_stmt_bind_param($stmt, "ssi", $questionNo, $answer, $type);
mysqli_stmt_execute($stmt);
}
}
}
二.将代码部署到服务器中,并修改客户端代码
1.将代码部署到服务器中
首先,你需要将上面的代码补全,由于时间问题,我并没有提供完整的代码
其次,在你的网站根目录中创建一个文件夹“API”(好吧,这个名字其实无所谓,你也可以不创建,直接将代码丢到根目录中),类似于下面这样
2.修改客户端代码或自己编写客户端
首先,你需要下载我提供的客户端,你也可以自己编写一个客户端
在我提供的客户端中,应该有以下几个脚本
你需要修改一下几个地方
- 脚本中的API地址,修改为你的API地址
- 删除权限验证代码
- 将一些没用的代码删除,比如(通知提示框,提交用户代码)
下面我将提供部分修改后的代码(你需要根据实际情况修改代码)
填写脚本修改后的参考代码
// ==UserScript==
// @name 题库自动化-填写
// @namespace https://www.lichuanjiu.top/
// @version 3.0.1
// @description 用于题库自动化处理
// @author 李传玖
// @match https://tiku.kgc.cn/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=kgc.cn
// @grant none
// ==/UserScript==
(function () {
'use strict';
// Your code here...
//定义用户脚本版本
var version = "3.0.1";
//判断用户位置是否是用户首页
var nowURL = window.location.href;
if (!(nowURL == "https://tiku.kgc.cn/testing/unified/exam")) {
document.body.onkeydown = function (e) {
if (e.ctrlKey && e.altKey && e.code == "KeyJ") {
showMain();
}
}
//创建dialog对象
var dialog = document.createElement("dialog");
//创建style元素
var style = document.createElement("style");
dialog.setAttribute("id", "Mydialog");
dialog.innerHTML = '<div class="input"><h1>欢迎使用题库脚本服务</h1><label for="switch"> 开关</label><input type="checkbox" name="switch" id="switch" ><label for="accuracy">正确率</label><input type="text" name="accuracy" id="accuracy" value="100"></div><div class="last"><button id="MyBtnConfirm">确定</button></div><div class="copy"><span>© <a href="https://itziyuanwang.top" target="_blank">IT资源网产品</a></span> <span><a href="https://www.itziyuanwang.top/supportOur.php" target="_blank">赞助开发</a></span></div>'
style.innerHTML = '#Mydialog {z-index: 99999; background-color: #fff; border-radius: 10px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); position: fixed;top: 50%;transform: translate(0, -50%);padding: 20px;text-align: center;margin: auto;} #Mydialog label {display: block; margin-top: 0.3em;font-weight: bold;} #Mydialog input[type="checkbox"], #Mydialog input[type="text"] {width: 30%; padding: 10px;margin-top: 0.2em; border: 1px solid #ccc;cursor: pointer; border-radius: 5px;}#Mydialog input[type="checkbox"]:focus, #Mydialog input[type="text"]:focus {outline: none;border-color: #007BFF;}#Mydialog button {background-color: #007BFF;color: #fff;padding: 10px 20px; border: none; border-radius: 5px;cursor: pointer; margin-top: 20px;}#Mydialog button:hover {background-color: #005fc4;}#Mydialog button:active {animation: btnactive 0.5s linear reverse;}@keyframes btnactive {0% {background-color: #005fc4;}50% {background-color: #00254d;}100% {background-color: #005fc4;}}#Mydialog .copy {text-align: center;margin-top: 20px; }#Mydialog .copy a {text-decoration: none;color: #007BFF;}#Mydialog .copy a:hover {text-decoration: underline;}';
//向页面中添加元素
document.body.append(dialog);
document.head.append(style);
refreshBtnAppearance();
}
var all = null;
analyzeTheTopic();
function analyzeTheTopic() {
//定义两个变量存储信息判断操作
var testAddress = "https://tiku.kgc.cn/testing/exam/paper"; //课程复习型地址
var testAddress_1 = "https://tiku.kgc.cn/testing/exam/createSkillPaper" //专项技能型地址
//获取当前所在位置
if (!(nowURL == testAddress || nowURL == testAddress_1)) {
return;
}
if (!getUserScriptStatus()) {
return;
}
initializationAccuracy();
setTimeout(() => {
if (getUserScriptStatus()) {
all = document.getElementsByClassName("sec");
var tempi = 0;
console.log(all.length);
var idList = "";
for (var i = 0; i < all.length; i++) {
var temppre = all[i].getElementsByTagName("pre");
var thisze = temppre[0].getElementsByTagName("img");
if (thisze.length == 1) {
console.log(thisze[0].src);
var params = queryURLparamsRegEs5(thisze[0].src)["relativePath"];
var encryptionId = getID(params);//到这里我们获取到了题目的加密ID
//获取真实ID
var realID = getID(encryptionId) + "/" + (getIDNum(encryptionId) - tempUserID);
idList = idList + realID + ";";
}
}
operation(idList);
}
}, 2000);
setTimeout(() => {
if (getUserScriptStatus()) {
$.ajax({ type: "get", dataType: "text", url: "https://tiku.kgc.cn/testing/gra/now", success: function (data) { } });
//点击交卷
document.getElementById("putIn").click();
document.getElementById("putInBtn").click();
}
}, 3000);
setTimeout(() => {
if (getUserScriptStatus()) {
//关闭提示
document.getElementById("closeReturnDialog").click();
}
}, 8000);
}
function operation(idList) {
var data = new FormData();
data.append("id", idList);
//创建异步对象
var xhr = new XMLHttpRequest();
//设置请求的类型及url
xhr.open('post', '你的API地址');
//post请求一定要添加请求头才行不然会报错
// xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
//发送请求
xhr.send(data);
xhr.onreadystatechange = function () {
// 这步为判断服务器是否正确响应
if (xhr.readyState == 4 && xhr.status == 200) {
//拿到服务器的数据,并解析
var result = parseData(xhr.responseText);
//填写数据到页面
fillIn(result);
console.log(result);
}
};
}
// https://tiku.kgc.cn/testing/cdn/getImage?relativePath=0012000/1543303458188/616904c46eec36797abd9929c5dd34bf.jpg&imageType=2
//获得参数
function queryURLparamsRegEs5(url) {
let obj = {}
let reg = /([^?=&]+)=([^?=&]+)/g
url.replace(reg, function () {
obj[arguments[1]] = arguments[2]
})
return obj
}
function getID(parameter) {
var index = parameter.lastIndexOf("/");
var ID = parameter.substr(0, index);
return ID;
}
function getIDNum(encryptionId) {
var index = encryptionId.lastIndexOf("/");
var IDNum = encryptionId.substr(index + 1, encryptionId.length);
return IDNum;
}
//解析来自后台的数据
function parseData(data) {
//去除data中最后一个“;”
var index = data.lastIndexOf(";");
data = data.substr(0, index);
var pData = data.split(";");
return pData;
}
//将参数填写到页面
function fillIn(parameter) {
var arr = ["A", "B", "C", "D", "E"];
//获取根据用户输入的正确率获取的需要填写的错题量
var wrongTopic = getCookie("wrongTopic");
for (var i = 0; i < parameter.length; i++) {
//判断题目是否在数据库中记录
if (parameter[i] != -1) {
var listOfOptions = all[i].getElementsByTagName("input");
//判断题目是多选还是单选
if (parameter[i].length > 2) {//这是一道多选题
var multipleSelectionList = parameter[i].split(",");
multipleSelectionList.forEach(element => {
var index = arr.map(item => item).indexOf(element);
listOfOptions[index].click();
});
} else {//单选题
var index = arr.map(item => item).indexOf(parameter[i]);
//扰动正确答案,达到控制正确率的效果
if (wrongTopic > 0) {
if (index == 0) {
index = 3;
} else {
index--;
}
wrongTopic--;
}
listOfOptions[index].click();
}
}
}
}
function setCookie(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays);
document.cookie = c_name + "=" + escape(value) +
((expiredays == null) ? "" : ";expires=" + exdate.toGMTString()) + ";path=/";
}
function getCookie(name) {
var cookies = document.cookie;
var list = cookies.split("; "); // 解析出名/值对列表
for (var i = 0; i < list.length; i++) {
var arr = list[i].split("="); // 解析出名和值
if (arr[0] == name) {
return decodeURIComponent(arr[1]); // 对cookie值解码
}
}
return "";
}
//计算正确率,写入cookie
function initializationAccuracy() {
all = document.getElementsByClassName("sec");
//获取百分值
var accuracy = getCookie("accuracy");
//计算应该错误和正确的题量
var wrongTopic = parseInt(all.length - ((accuracy / 100) * all.length));
console.log("正确率:" + accuracy + "..." + wrongTopic);
setCookie("wrongTopic", wrongTopic);
}
//按钮状态刷新
function refreshBtnAppearance() {
document.getElementById("switch").checked = getUserScriptStatus();
document.getElementById("accuracy").value = getCookie("accuracy");
}
//获取用户脚本状态
function getUserScriptStatus() {
//读取用户脚本状态
var state = getCookie("scriptStatus");
return state == "1" ? true : false;
}
function showAdvertisement(url, tips) {
const dialogStyleStr = "width: 60%;height: 100%;border: 0px;position: absolute;text-align: center; margin: auto;";
const iframeStyleStr = "width: 100%;height: 90%;border: 0px;";
const closeBtnStyleStr = " width: 100px;height: 30px;background-color: rgb(8, 179, 8);border-radius: 5px;color: white;font-size: 20px;cursor: pointer;border-width: 0px;";
const textStyleStr = "width: 100%; text-align: center; padding: 0px; margin: 0px ;border: 0px; font-size:2.5em; font-weight: bold;";
// 创建一个dialog元素
var dialog = document.createElement("dialog");
// 设置dialog的样式
dialog.setAttribute("style", dialogStyleStr);
// 创建一个iframe 元素
var iframe = document.createElement("iframe");
// 设置iframe的src
iframe.setAttribute("src", url);
iframe.setAttribute("style", iframeStyleStr);
// 创建一个closeBtn元素
var closeBtn = document.createElement("button");
// 设置closeBtn的样式
closeBtn.setAttribute("style", closeBtnStyleStr);
// 设置closeBtn的文本
closeBtn.textContent = "关闭";
// 创建一个text元素
var text = document.createElement("h1");
// 设置text的样式
text.setAttribute("style", textStyleStr);
// 设置text的文本
text.textContent = tips;
dialog.appendChild(iframe);
// 将closeBtn添加到dialog中
dialog.appendChild(closeBtn);
// 将text添加到dialog中
dialog.appendChild(text);
// 将dialog添加到body中
document.body.append(dialog);
// 点击closeBtn时关闭dialog
closeBtn.onclick = function () {
dialog.close();
}
//显示dialog
dialog.showModal();
}
function showMain() {
if (dialog.open) {
return;
}
dialog.showModal();
document.getElementById("MyBtnConfirm").onclick = btnConfirm;
document.getElementById("accuracy").oninput = function () {
inputCheck(this);
};
}
function btnConfirm() {
//获取元素选择框
let checkbox = document.getElementById("switch").checked;
let accuracy = document.getElementById("accuracy").value;
if (isNaN(accuracy) || accuracy > 100 || accuracy < 1) {
accuracy = 100;
}
if (!getUserScriptStatus() && checkbox) {
//写入cookie
setCookie("scriptStatus", checkbox ? "1" : "-1");
}
document.getElementById("accuracy").value = accuracy;
setCookie("scriptStatus", checkbox ? "1" : "-1");
setCookie("accuracy", accuracy);
if (getUserScriptStatus()) {
analyzeTheTopic();
}
//关闭dialog
dialog.close();
}
function inputCheck(element) {
element.value = element.value.replace(/[^\d]/g, '');
if (element.value > 100) {
element.value = 100;
return;
}
if (element.value < 1 && element.value != "") {
element.value = 1;
}
}
})();
当你确定代码都修改完成,并测试没有问题的时候,你就可以在你的浏览器中安装油猴插件,并在插件中添加修改后的脚本,至于如何编写油猴脚本,还请您自行百度学习。
3.你可能会遇到的一些问题
在这里,我将会列举出一些您可能遇到的一些问题
- A 脚本测试没有问题了,但是我在题库页面中就是没有办法运行该脚本
- B 请注意,我们的脚本代码中有这么一行
// @match https://tiku.kgc.cn/*
这表示,该脚本将在”https://tiku.kgc.cn/*“这个站点中被激活并运行,如果您访问的题库地址不是这个,请尝试使用该地址的题库,或者您可以修改脚本中的适用范围
A 脚本成功激活了并运行了,但是没有效果
B 按下F12 打开浏览器控制台,检查脚本是否有运行报错,如果有,请解决
A 按下快捷键,能够激活页面,但是无法正确刷题
B 按下F12 打开浏览器控制台,如果遇到的是类似于下面的错误,这意味着出现了跨域请求错误
这时,你需要在你的API中添加以下代码header("Access-Control-Allow-Origin:*");
B 如果你遇到的是类似于下面的错误:
这意味你没有配置https,你需要为你的脚本服务站点启用443端口,并配置ssl证书,同时,你的脚本服务器地址API也应该使用https协议,如果你没有ssl证书,你可以使用”phpstudy_pro“这个软件生成开发者测试证书,类似于下面这样然后通过https协议访问你的API地址,在这个界面中,可能会弹出一个关于ssl证书错误的安全提示
你点击高级,选择”无视风险,继续前往“。注意,该方式有一些缺点:
在一段时间后,该问题还会出现,你需要重复上面的操作
当你尝试更换浏览器时,你有可能还会遇到这个问题,你需要重复上面的操作
三.下载地址
本着节约时间的观念,我并不希望任何一个学习IT的人员把时间浪费在无意义的事情上,我决定最新版本免费,您下载后可以通过联系我们页面或邮箱联系又或者站内留言等形式告知联系我们,我们免费为您开通激活该服务
点击前往下载最新可用版
如果你还有其他问题,您可以通过下面的链接联系我们