nuym's blog

返回

此教材仅供学习和参考,学科网及组卷网仍需要会员才能正常访问相关试卷与答案。
plaintext

教程#

前置准备:安装油猴(Tampermonkey)插件#

安装油猴脚本前,需先在浏览器中安装油猴插件(核心管理器)。不同浏览器的安装方式略有差异,以下是主流浏览器的详细步骤:

Chrome 浏览器(含 Chromium 内核衍生浏览器)#

方法一:应用商店直接安装(推荐,需网络可访问 Chrome 应用商店)

  1. 打开 Chrome 浏览器,在地址栏输入 chrome.google.com/webstore 进入 Chrome 应用商店;

  2. 在搜索框中输入“Tampermonkey”,点击搜索结果中的官方插件(图标为黑色背景上的黄色猴子);

  3. 点击“添加至 Chrome”,在弹出的确认窗口中选择“添加扩展程序”;

  4. 安装完成后,浏览器右上角会出现油猴图标,表明插件安装成功。

方法二:本地文件安装(适用于无法访问应用商店的情况)

  1. 下载油猴插件的 .crx 格式安装包(需从可信来源获取,如油猴官网、Greasy Fork 配套资源页);

  2. 打开 Chrome 浏览器,在地址栏输入 chrome://extensions 进入扩展管理页面;

  3. 开启页面右上角的“开发者模式”开关;

  4. 将下载好的 .crx 文件直接拖拽到扩展管理页面中;

  5. 在弹出的提示框中点击“添加扩展程序”,完成安装后查看右上角油猴图标是否正常显示。

提示:360 安全浏览器、QQ 浏览器等 Chromium 内核国产浏览器,可参考此方法安装,步骤基本一致(扩展管理页面入口可能为:右上角扩展图标 → 管理 → 更多扩展)。

Edge 浏览器#

  1. 打开 Edge 浏览器,点击右上角三个点(设置及更多),选择“扩展”;

  2. 在扩展页面中点击“获取 Microsoft Edge 扩展”,进入 Edge 应用商店;

  3. 搜索“Tampermonkey”,找到官方插件后点击“获取”,等待安装完成;

  4. 安装成功后,可在浏览器右上角扩展栏中找到油猴图标(若未显示,可点击扩展图标展开列表,勾选“固定”将其显示在工具栏)。

  5. 在地址栏输入 edge://extensions/。在页面左下角找到并打开“开发人员模式”开关,允许加载已解压的扩展程序。

Firefox 浏览器#

  1. 打开 Firefox 浏览器,在地址栏输入 addons.mozilla.org 进入 Firefox 附加组件商店;

  2. 搜索“Tampermonkey”,点击搜索结果中的官方插件;

  3. 点击“添加到 Firefox”,在弹出的确认窗口中选择“添加”;

  4. 安装完成后,浏览器右上角会出现油猴图标,表明插件已生效。

提示:Firefox 不支持直接拖拽 .crx 文件安装,需下载专用的 .xpi 格式安装包或通过官方商店安装。

Safari 浏览器(Mac 系统)#

  1. 打开 Mac 上的 App Store,搜索“Tampermonkey”;

  2. 下载并安装官方版本的 Tampermonkey 应用;

  3. 安装完成后,打开 Safari 浏览器,点击顶部菜单栏“Safari”→“设置”→“扩展”;

  4. 在扩展列表中找到“Tampermonkey”,勾选“启用”,并可将其拖拽到浏览器工具栏方便使用。

核心步骤:安装油猴脚本#

在浏览器中打开 https://greasyfork.org/,搜索组卷网学科网试卷处理下载打印,请注意辨别作者为nuym

若您搜索不到,你也可以选择直接点击该链接 组卷网学科网试卷处理下载打印

点击 安装此脚本->安装

下载#

如果你安装正确,你会看到这样的图片。

安装成功的图片

对的,我叛变了,沙比亳州一中招生办和教务办,至今忘不了对我的志愿表的冷笑和招生的傲娇,两个字,沙比。

找到你心意的卷子,点击打印试卷按钮,选择打印方式即可。

如果需要保存则使用另存为PDF

另存为PDF

如果是自己组的卷子,则需要点击分享试卷,然后在新的窗口打开链接,继续上面的操作即可。

教程到此结束。

开发过程#

随便打开一个网页,使用开发者工具,鼠标选中查看对应组件。

exam-cnt

这里我们定位到组件exam-cnt

分析结构体

 <!--试卷标签-->
<section class="exam-list" data-sys-id="43b73e6383b0d8-e4e78ff3bc8138">

<!--存储容器-->
<div class="sec-item"> 

<!--试卷大题类型-->
<h4 id="1" class="sec-title clearfix">

<!--详细题目-->
<div class="sec-list">
...
</div>
html

由此我们已经拆出了结构,接下来逐步分析。

基于上述定位的exam-cnt核心容器,我们继续对试卷标签下的大题标题单道题目的DOM结构进行精细化拆解:

1. 大题标题模块(h4.sec-title)#

这是试卷中「填空题/选择题/解答题」等大题类型的核心容器,完整结构和字段含义如下:

<h4 id="1" class="sec-title clearfix">
    <!-- 大题类型名称,如“一、填空题” -->
    <span>一、填空题</span>
    <!-- 功能按钮:添加该题型下的试题 -->
    <a href="javascript:void 0" class="add-sec-ques" qtid="2702">添加题型下试题</a>
</h4>
html
  • id="1":该大题在试卷中的序号标识(如第1大题);
  • class="sec-title clearfix":样式类,clearfix用于清除浮动,保证标题布局稳定;
  • span标签:承载大题的显示名称(核心文本内容);
  • a.add-sec-ques:操作按钮,qtid="2702"是该题型的唯一标识(后端关联该题型的业务ID)。

2. 题目列表容器(div.sec-list)#

sec-list是单道题目(tk-quest-item)的父容器,所有该大题下的题目都嵌套在这个容器内。

3. 单道题目核心模块(div.tk-quest-item)#

这是每一道具体试题的最外层容器,包含题目基础信息、题干、知识点、操作按钮等所有核心内容,我们按子模块逐一拆解:

3.1 题目外层标识(核心属性)#

<div class=" tk-quest-item  quesroot  " 
     questionindex="0" 
     questionid="26116772" 
     bankid="11" 
     data-sys-id="df46b43b8420a8-8d2ed46df225e8">
html
  • questionindex="0":该题目在当前大题中的序号(从0开始计数,如大题下第1题对应index=0);
  • questionid="26116772":题目唯一业务ID(核心标识,关联后端题库数据);
  • bankid="11":题库ID(标识该题目所属的题库);
  • data-sys-id:前端系统生成的唯一标识(用于前端DOM操作、事件绑定)。

3.2 题目附加信息模块(div.ques-additional)#

承载题目来源、难度、标签、解题方法等辅助信息,分为两个子部分:

3.2.1 题目来源(div.top-msg)#
<div class="top-msg">
    <span class="addi-msg"> 
        <a href="/11p3017178.html" 
           title="原始出处:上海市闸北第八中学2025-2026学年高一上学期期末质量检测数学试题" 
           target="_blank" 
           class="addi-msg ques-src">24-25高一上·上海·期末</a>
    </span>
</div>
html
  • a.ques-src:题目原始来源链接,title属性存储完整来源名称,显示文本为简化后的来源信息。
3.2.2 题目基础信息(div.msg-box)#

分为左侧(题型、难度)和右侧(标签、解题方法):

<div class="msg-box">
    <!-- 左侧:题型+难度 -->
    <div class="left-msg">
        <span class="addi-info">
            <span class="info-cnt">填空题-单空题</span> <!-- 具体题型细分 -->
        </span>
        <b class="gap">|</b> <!-- 分隔符 -->
        <span class="addi-info">
            <span class="info-cnt">容易(0.94)</span> <!-- 难度:文字+难度系数 -->
        </span>
    </div>
    
    <!-- 右侧:标签+解题方法 -->
    <div class="right-msg">
        <span class="tag yazhou">名校</span> <!-- 题目标签(如名校/真题等) -->
        <div class="jieti-btn">
            <span class="title-box">解题方法</span>
            <div class="method-list">
                <a class="item" target="_blank" href="/gzsx/jtff149575">根据集合包含关系求参数值或范围</a>
            </div>
        </div>
    </div>
</div>
html

3.3 题干核心模块(div.wrapper.quesdiv)#

承载题目正文、知识点、答案等核心内容:

<div class="wrapper quesdiv" id="quesdiv26116772">
    <!-- 题干内容 -->
    <div class="exam-item__cnt ">
        1. 已知集合<img src="xxx.png" style="vertical-align:middle;">,...,则实数<img src="xxx.png">的值为<bk size="10" index="1" type="underline">__________</bk>.
    </div>
    
    <!-- 隐藏的知识点/答案模块(默认不显示) -->
    <div hidden="" class="exam-item__opt">
        <!-- 知识点 -->
        <div class="item knowlegde">                
            <p class="knowledge-box">
                <span class="knowledge-title primary-color">【知识点】</span>  
                <span data-type="knowledgeItem" class="knowledge-item">   
                    <a href="/gzsx/zsd27966/" target="_blank" class="knowledge-name font-item" cid="27966">根据集合的包含关系求参数</a>
                    <a href="javascript:void 0" class="knowledge-explain primary-button" cid="27966">解读</a>
                </span>
            </p>            
        </div>            
        <!-- 答案(此处为空,实际场景会填充) -->
        <div class="item answer"></div>
    </div>
</div>
html
  • id="quesdiv26116772":与questionid关联,唯一标识该题干容器;
  • bk标签:填空题的空行占位符,index="1"标识第1个空;
  • exam-item__opt:默认hidden,需通过前端交互(如点击“显示答案”)展示知识点/答案。

3.4 题目使用数据模块(div.exam-item__custom)#

存储用户使用该题目的频次等个性化数据(默认隐藏):

<div class="exam-item__custom" hidden="">
    <div class="month-used">
        <span class="font-item-ligth">您最近一年使用:<em class="em-anchor2" id="pmd_26116772">0</em>次</span>
    </div>
</div>
html

3.5 题目操作与统计模块(div.exam-item__info)#

包含题目发布时间、组卷次数、引用来源、功能按钮:

<div class="exam-item__info clearfix">
    <!-- 左侧:统计信息 -->
    <div class="info-msgs">
        <span class="no-bound" title="2025/02/20">2025/02/20</span> <!-- 发布/录入时间 -->
        <b class="gap">|</b>
        <span title="791次组卷">791次组卷</span> <!-- 组卷使用频次 -->
        <b class="gap">|</b>
        <span class="look-more-src"> <!-- 多卷引用来源 -->
            <span class="info-txt font-item-ligth">11卷引用:xxx</span>
            <div class="more-src-links" hidden="hidden"> <!-- 展开显示所有引用来源 -->
                <a href="/11p2455075.html" target="_blank" class="src-item">xxx试题</a>
                ...
            </div>
        </span>
    </div>

    <!-- 右侧:操作按钮 -->
    <div class="ctrl-box">
        <a class="ctrl-btn btn_ques_similarq" href="javascript: void 0">相似题</a>
        <a class="ctrl-btn btn_ques_error" href="javascript: void 0">纠错</a>
        <a class="ctrl-btn" target="_blank" href="/11q26116772.html">详情</a>
        <a class="ctrl-btn btn_ques_collect" id="coll_26116772" href="javascript: void 0">收藏</a>
        <a class="ctrl-btn btn_ques" id="quesselect26116772" href="javascript:void 0">加入试题篮</a>
    </div>
</div>
html

由此,我们已经完成对结构的分析,那么进行脚本开发(实际开发没有这么细致,只需大致观察结构即可。)

编写代码#

初始化容器#

创建两个核心容器,分别存储最终打印内容和待收集的答案(用于「答案移至末尾」模式):

const newPageBody = document.createElement('div'); // 存储最终打印的所有内容
newPageBody.id = 'zujuanjs-reformatted-content';
const answersSection = []; // 临时存储答案,用于末尾汇总
javascript

遍历页面结构,按类型处理元素#

页面中题目和大题标题的 DOM 结构是按顺序排列的,通过querySelectorAll(‘.sec-title, .tk-quest-item.quesroot’)获取所有大题标题和题目容器,然后逐一遍历处理:

const sections = document.querySelectorAll('.sec-title, .tk-quest-item.quesroot');
sections.forEach((section) => {
    // 处理1:如果是大题标题(如“一、填空题”)
    if (section.classList.contains('sec-title')) {
        const span = section.querySelector('span');
        if (span) {
            const titleDiv = document.createElement('div');
            titleDiv.className = 'zujuanjs-section-title';
            titleDiv.textContent = span.textContent.trim(); // 提取标题文本
            newPageBody.appendChild(titleDiv); // 添加到打印容器
        }
    }
    // 处理2:如果是题目容器(核心:提取题干和答案)
    else if (section.classList.contains('tk-quest-item') && section.classList.contains('quesroot')) {
        const newQuestionDiv = document.createElement('div'); // 单个题目的容器
        newQuestionDiv.className = 'zujuanjs-question';

        // 找到题干和答案的父容器
        const quesdiv = section.querySelector('.wrapper.quesdiv');
        if (quesdiv) {
            // ========== 子步骤1:处理题干 ==========
            if (includeQuestions) { // 仅当需要包含题干时执行
                const cntDiv = quesdiv.querySelector('.exam-item__cnt'); // 题干DOM
                if (cntDiv) {
                    // 克隆题干元素(避免修改原页面DOM)
                    newQuestionDiv.appendChild(cntDiv.cloneNode(true));
                }
            }

            // ========== 子步骤2:处理答案 ==========
            const optDiv = quesdiv.querySelector('.exam-item__opt'); // 答案DOM(包含知识点、答案)
            if (optDiv) {
                // 移除冗余的知识点模块(只保留答案)
                const knowledgeBox = optDiv.querySelector('.knowledge-box');
                if (knowledgeBox) knowledgeBox.remove();

                // 情况A:答案与题干一起打印
                if (includeAnswers) {
                    newQuestionDiv.appendChild(optDiv.cloneNode(true));
                }
                // 情况B:答案移至末尾 → 先存入临时数组,不立即添加
                else if (answersAtEnd) {
                    answersSection.push(optDiv.cloneNode(true));
                }
            }
        }

        // 将处理好的题目(含/不含答案)添加到打印容器
        newPageBody.appendChild(newQuestionDiv);
    }
});
javascript

替换页面内容并触发打印#

function performPrint(includeQuestions, includeAnswers, answersAtEnd) {
    const newPageBody = getReformattedContent(includeQuestions, includeAnswers, answersAtEnd);
    // 添加试卷标题(可选)
    const titleElement = document.querySelector('.exam-title .title-txt');
    if (titleElement) {
        const pageTitle = titleElement.textContent.trim();
        const titleDiv = document.createElement('div');
        titleDiv.id = 'page-title';
        titleDiv.textContent = pageTitle;
        newPageBody.insertBefore(titleDiv, newPageBody.firstChild);
    }
    // 清空原页面,替换为处理后的内容
    document.body.innerHTML = '';
    document.body.appendChild(newPageBody);
    // 触发浏览器打印
    window.print();
}
javascript

完整代码阅读

https://github.com/bzyzh/xkw-zujuan-script

鸣谢#

nuym 主要开发及撰写文章

WorkingFishQ 辅助开发

ResonanceForge 辅助开发

ChatGPT 辅助撰写文章

学科网 组卷网 试卷提供

如何免费下载组卷网的试卷
https://www.nuym.cn/blog/zujuan-free-download-tutorial
Author nuym
Published at 2026年1月24日
正在加载评论系统...