Initializing

油猴脚本 获取国家中小学智慧教育平台教科书 PDF 版本

油猴脚本,需要浏览器中「允许发送弹出窗口及使用重定向」(地址栏右侧),否则 pdf 页面弹不出来。实在不行可以打开控制台看 pdf 的 url。

pdf 是矢量图(不是图片),文字都可以选中。

打开 国家中小学智慧教育平台 中任意教科书即可获取,记得登录。

Code by ChatGPT。原理

或者从 greasyfork 安装。

// ==UserScript==
// @name         国家中小学智慧教育平台获取教科书 PDF 版本
// @namespace    https://www.cnblogs.com/chargedcreeper/p/20015053
// @version      1.0
// @description  自动提取 PDF 请求中的 X-Nd-Auth id 并打开可直接访问的 PDF
// @match        *://basic.smartedu.cn/*
// @grant        unsafeWindow
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const opened = new Set();

    // Hook fetch
    const originalFetch = unsafeWindow.fetch;
    unsafeWindow.fetch = async function (...args) {
        const response = await originalFetch.apply(this, args);

        try {
            const request = args[0];

            let url = '';
            let headers = {};

            if (typeof request === 'string') {
                url = request;
                headers = args[1]?.headers || {};
            } else {
                url = request.url;
                headers = request.headers;
            }

            processRequest(url, headers);
        } catch (e) {
            console.error(e);
        }

        return response;
    };

    // Hook XMLHttpRequest
    const originalOpen = XMLHttpRequest.prototype.open;
    const originalSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;
    const originalSend = XMLHttpRequest.prototype.send;

    XMLHttpRequest.prototype.open = function (method, url, ...rest) {
        this._url = url;
        this._headers = {};
        return originalOpen.call(this, method, url, ...rest);
    };

    XMLHttpRequest.prototype.setRequestHeader = function (key, value) {
        this._headers[key] = value;
        return originalSetRequestHeader.call(this, key, value);
    };

    XMLHttpRequest.prototype.send = function (...args) {
        try {
            processRequest(this._url, this._headers);
        } catch (e) {
            console.error(e);
        }

        return originalSend.apply(this, args);
    };

    function processRequest(url, headers) {
        if (!url) return;

        if (!url.toLowerCase().includes('.pdf')) return;

        if (opened.has(url)) return;

        let auth = null;

        // Headers 可能是 Headers 对象
        if (headers instanceof Headers) {
            auth = headers.get('X-Nd-Auth');
        } else {
            auth =
                headers['X-Nd-Auth'] ||
                headers['x-nd-auth'];
        }

        if (!auth) return;

        const match = auth.match(/id="([^"]+)"/);

        if (!match) return;

        const id = match[1];

        // 删除 "_纯图版"
        const cleanedUrl = url.replace('_%E7%BA%AF%E5%9B%BE%E7%89%88', '');

        const finalUrl =
              cleanedUrl + (cleanedUrl.includes('?') ? '&' : '?') +
              'accessToken=' + encodeURIComponent(id);

        opened.add(url);

        console.log('PDF URL:', finalUrl);

        window.open(finalUrl, '_blank');
    }
})();
posted @ 2026-05-11 16:35  Po7ed  阅读(150)  评论(0)    收藏  举报