若剔除公共依赖库(Typr.js、RxJS、md5 等第三方库)以及 Vue/Pinia 框架代码,真正属于业务逻辑的自定义代码重合率显著降低。指控方将第三方库代码计入“唯一行重合”,人为夸大比例。
实际业务逻辑重合行:经去除第三方库后,两脚本在业务实现层的重合行数不足 200 行,且这些重合均属于对学习通页面固定 DOM 结构、固定字符串、固定流程的自然实现。
连续代码块重合:指控方所列的连续代码块均为单一功能实现(如点击按钮、判断字符串),属于任何开发者都会采用的直接写法,不能作为抄袭证据。
三、对指控方“高价值业务逻辑重合证据”的反驳
指控方列举了 12 条代码片段,声称是“抄袭证据”。以下逐条说明其真实原因:
证据 1:作业状态判断
js
if (iframeDocument.documentElement.innerText.includes("已完成") || iframeDocument.documentElement.innerText.includes("待批阅"))
反驳:学习通作业页面完成后的提示文本就是“已完成”或“待批阅”,这是页面固有字符串,任何脚本要判断作业状态都必须用这两个字符串,不存在第二种写法。
证据 2:任务点图标定位
js
const ansJobIcon = (_b = iframe.parentElement) == null ? void 0 : _b.querySelector(".ans-job-icon");
反驳:学习通任务点图标的固定类名为 ans-job-icon,所有脚本获取该元素都会使用 .ans-job-icon 选择器,这是对 DOM 结构的直接引用,并非独创。
证据 3:innerbook 分支判断
js
} else if (["innerbook"].some((type) => iframeSrc.includes("modules/" + type))) {
反驳:学习通电子书模块的 URL 固定包含 /modules/innerbook,判断逻辑只能基于此字符串,任何自动刷课脚本都会采用相同的条件。
证据 4:下一章节点击
js
document.querySelector(".jb_btn.jb_btn_92.fr.fs14.nextChapter").click();
反驳:学习通“下一章节”按钮的类名固定为 .jb_btn.jb_btn_92.fr.fs14.nextChapter,要自动点击就必须使用这个选择器,这是唯一路径。
证据 5:题型文本解析
js
questionTypeText = this.removeHtml(colorShallowElement).slice(1, 4) || "";
反驳:学习通作业页面中题型文字被 colorShallowElement 包裹,且通常以“【】”或“()”括起,slice(1,4) 是为了去掉首尾括号,这是对页面格式的通用处理方式,不同脚本很可能写出相同代码。
证据 6:媒体节点获取
js
const mediaElement = iframeDocument.documentElement.querySelector(mediaType);
反驳:获取视频或音频元素的标准 DOM 方法,写法唯一,无独创性。
证据 7:字体解密选择器
js
const elements = iframeDocument.querySelectorAll(".font-cxsecret");
反驳:学习通加密字体的类名固定为 font-cxsecret,任何解密脚本都必须使用该选择器,否则无法定位加密元素。
证据 8、9:函数签名
js
const processWork = async (iframe, iframeDocument, iframeWindow) => {
const processMedia = async (mediaType, iframeDocument, iframe) => {
反驳:处理 iframe 相关任务时,用 iframe、iframeDocument、iframeWindow 作为参数名是最直观的命名习惯,不同开发者独立编写时极易撞名。函数功能相似时,参数结构自然相同。
证据 10:iframe 收集逻辑
js
return Array.from(element.querySelectorAll("iframe"));
反驳:获取所有 iframe 的标准 DOM 方法,写法唯一。
证据 11:答题分支判断
js
if (question.type === "0" || question.type === "1") {
反驳:用数字表示题型是常见的数据设计,0=单选、1=多选是普遍编码习惯,不存在独创性。
证据 12:视频/音频分发逻辑
js
if (iframeSrc.includes("video")) {
return processMedia("video", iframeDocument, iframe);
} else if (iframeSrc.includes("audio")) {
return processMedia("audio", iframeDocument, iframe);
}
反驳:根据 URL 字符串是否包含 "video" 或 "audio" 进行分发,是唯一直观的方法,任何脚本都会这样实现。
指控方称发现“多处连续 3 行完全相同业务代码块”,但所列位置对应的代码均属于对学习通页面固定结构的直接操作,如点击按钮、判断字符串、获取元素,这些操作天然具有唯一实现方式,不能作为抄袭证据。
双方均使用了相同的第三方库(Typr.js、RxJS、md5 等),导致大量基础代码重合;
双方均针对学习通页面的固定 DOM 结构、固定字符串、固定类名编写脚本,这些操作天然具有唯一实现方式;
双方在功能设计上选择了相似的模块划分(如 iframe 处理、答题、媒体播放),这是同类脚本的自然架构演进。
最后我希望平台可以认真核查,保护正常开发者的权益
致敬脚本猫管理员