终于不用看到CSDN该死的弹窗限制了

想必大家在网上搜索解决问题解决方案时都会有这样的经历,明明找到了想要的解决问题的代码,想要一键复制到项目代码中,但有些网页限制了你的复制行为,可能让你登录账号、关注博主,更有甚者直接收费,其中比如CSDN,所以秉着互联网的开源精神我写个脚本来解决这问题,但由于个游览器的差异本文只针对我经常使用的Chrome游览器进行讲解。

开发脚本

根据对CSDN网页结构的了解我们主要针对包裹代码的<pre><code> 标签,还有网页对用户复制操作的监听的处理。

ini 复制代码
// ==UserScript==
// @name         终极复制解锁(捕获阶段拦截 + 全面清理)
// @namespace    http://tampermonkey.net/
// @version      1.6
// @description  彻底解除复制限制,包括 pre > code 无法复制的问题
// @author       You
// @match        *://*/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    // 需要拦截的事件类型(这些事件常被用于限制复制)
    const BLOCKED_EVENTS = [
        'copy', 'cut', 'selectstart', 'contextmenu', 'selectionchange', 'mousedown', 'mouseup'
    ];
    console.log(`脚本启动`);
    // ---------- 1. 捕获阶段拦截事件传播,但不阻止默认行为 ----------
    function stopPropagationOnly(e) {
        e.stopPropagation(); // 阻止事件传播到页面注册的监听器
        // 不调用 preventDefault,保证浏览器的默认复制行为能执行
    }

    BLOCKED_EVENTS.forEach(eventType => {
        document.addEventListener(eventType, stopPropagationOnly, true); // 捕获阶段
        window.addEventListener(eventType, stopPropagationOnly, true);
    });

    // ---------- 2. 拦截后续 addEventListener 调用 ----------
    const originalAddEventListener = EventTarget.prototype.addEventListener;
    EventTarget.prototype.addEventListener = function(type, listener, options) {
        if (BLOCKED_EVENTS.includes(type)) {
            console.log(`[解锁脚本] 已阻止添加事件: ${type}`);
            return; // 忽略添加
        }
        return originalAddEventListener.call(this, type, listener, options);
    };

    // ---------- 3. 清除已有事件属性和 CSS 限制 ----------
    function removeRestrictions(root) {
        if (!root) return;
        // 兼容 iframe 传入的 window
        if (root.document) root = root.document;

        // 清理 document 对象
        if (root.nodeType === Node.DOCUMENT_NODE) {
            root.oncopy = null;
            root.oncut = null;
            root.onselectstart = null;
            root.oncontextmenu = null;
            root.onselectionchange = null;

            // 添加强制选择样式
            const style = root.createElement('style');
            style.innerHTML = `
                * {
                    user-select: text !important;
                    -webkit-user-select: text !important;
                    -moz-user-select: text !important;
                    -ms-user-select: text !important;
                }
            `;
            root.head.appendChild(style);
        } else {
            // 普通元素
            root.oncopy = null;
            root.oncut = null;
            root.onselectstart = null;
            root.oncontextmenu = null;
            root.onselectionchange = null;
        }

        // 处理 Shadow DOM
        if (root.shadowRoot) {
            removeRestrictions(root.shadowRoot);
        }

        // 遍历所有后代元素
        if (root.querySelectorAll) {
            root.querySelectorAll('*').forEach(el => {
                el.oncopy = null;
                el.oncut = null;
                el.onselectstart = null;
                el.oncontextmenu = null;
                el.onselectionchange = null;
                if (el.shadowRoot) {
                    removeRestrictions(el.shadowRoot);
                }
            });
        }
    }

    // ---------- 4. 专门处理 pre 和 code 标签:克隆替换以移除所有事件监听器 ----------
    function unlockElements(root) {
        const selectors = ['pre', 'code'];
        selectors.forEach(selector => {
            const elements = root.querySelectorAll(`${selector}:not([data-unlocked])`);
            elements.forEach(el => {
                try {
                    const clone = el.cloneNode(true);
                    clone.setAttribute('data-unlocked', 'true');
                    el.parentNode.replaceChild(clone, el);
                    console.log(`[解锁脚本] 已替换 ${selector} 标签,移除了所有事件监听器`);
                } catch (e) {
                    console.warn(`[解锁脚本] 替换 ${selector} 失败`, e);
                }
            });
        });
    }

    // 初始执行
    removeRestrictions(document);
    unlockElements(document);

    // ---------- 5. 观察动态添加的内容 ----------
    const observer = new MutationObserver(mutations => {
        mutations.forEach(mutation => {
            mutation.addedNodes.forEach(node => {
                if (node.nodeType === Node.ELEMENT_NODE) {
                    removeRestrictions(node);
                    unlockElements(node);
                }
            });
        });
    });
    if (document.body) {
        observer.observe(document.body, { childList: true, subtree: true });
    }

    // ---------- 6. 处理 iframe ----------
    function unlockIframes(root) {
        root.querySelectorAll('iframe').forEach(iframe => {
            try {
                const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                if (iframeDoc) {
                    removeRestrictions(iframeDoc);
                    unlockElements(iframeDoc);
                    // 为 iframe 建立独立的观察者
                    const iframeObserver = new MutationObserver(() => {
                        removeRestrictions(iframeDoc);
                        unlockElements(iframeDoc);
                    });
                    if (iframeDoc.body) {
                        iframeObserver.observe(iframeDoc.body, { childList: true, subtree: true });
                    }
                }
            } catch(e) {
                // 跨域 iframe 忽略
            }
        });
    }

    // 定期扫描 iframe 和重复清理(防止页面动态重置)
    setInterval(() => {
        unlockIframes(document);
        removeRestrictions(document);
        unlockElements(document);
    }, 2000);
})();

运行脚本

脚本开发完了就到了实战的时候了,要在游览器中运行写好的脚本文件,以下提供您两种方式,以下方法方案都需要用户打开Chrome的开发者模式方能使用。

打开Chrome的开发者模式 打开Chrome的开发者模式 打开Chrome的开发者模式 !!!重要的事情说三遍

工具运行

使用Chrome扩展工具 在Chrome扩展应用商城下载Tampermonkey,操作Tampermonkey新建脚本,将之前写的脚本代码放入新建的脚本文件中,保存完毕后使用以下方法在网页中运行

方法一:通过扩展管理页面开启 "允许用户脚本"

这是 Chrome 138+ 版本的标准操作方式

  1. 进入管理页 :在 Chrome 右上角点击拼图图标,找到 Tampermonkey,点击右侧的 三个点 ,选择 "管理扩展程序"
  2. 查找开关 :在 Tampermonkey 的详情页面里,向下滑动,找到 "允许用户脚本" 的开关。
  3. 开启 :将其打开,然后完全重启一次 Chrome 浏览器

方法二:在控制台强制执行(如果方法一无效)

如果在详情页找不到上述开关,或者开启后依然无效,可以尝试用命令强制激活

  1. 确保开发者模式已开 :在地址栏输入 chrome://extensions/ 并回车,确认右上角的 "开发者模式" 处于开启状态

  2. 粘贴命令 :按 F12 打开开发者工具,切换到 Console(控制台) 标签页,将以下代码完整粘贴进去并回车:

    javascript

    php 复制代码
    chrome.developerPrivate.updateExtensionConfiguration({
        extensionId: "dhdgffkkebhmkfjojejmpbldmpobfkfo",
        userScriptsAccess: true
    });
  3. 重启 :执行完毕后,完全关闭 Chrome 并重新打开,再刷新网页试试

直接运行

使用 "代码片段" 保存终极脚本(一劳永逸)

如果你经常需要面对复杂的复制限制(比如你之前提到的 <pre> 标签问题),每次在控制台输入一大段代码会很麻烦。Chrome 的 "代码片段(Snippets)" 功能可以完美解决这个问题,相当于一个内置的、轻量级的脚本管理器。

  1. 打开Snippets面板

    • 打开开发者工具(F12)。
    • 切换到 Sources(源代码) 标签页。
  2. 创建并保存脚本

    • 点击 "New snippet"(新建代码片段)
    • 将我之前为你提供的那个增强版终极脚本 (包含了捕获阶段拦截、克隆替换 <pre><code> 标签、处理 Shadow DOM 等功能的完整代码)粘贴到右侧的编辑器中。
    • Ctrl+S 保存,你可以给它起个名字,比如 终极复制解锁
  3. 运行脚本

    • 以后在任何遇到复制限制的网页,只需打开开发者工具 -> Sources -> Snippets,找到你保存的脚本,右键点击并选择 "Run"(运行) ,或者点击右下角的运行按钮(一个类似播放键的图标)即可。

这样,你就拥有了一个不需要 Tampermonkey 也能随时调用的 "终极解锁工具"。

相关推荐
Xp021911032 分钟前
知网研学、万方、WPS、大以论文四大排版工具横评,新用户免费排版等你领!
前端·css·html·生活·wps·论文排版
全栈技术负责人3 分钟前
老项目新需求AI前端开发指南
前端·ai编程
周凡12313 分钟前
AI 时代的 Web JavaScript 逆向分析实践与思考
前端·javascript·人工智能
jerryinwuhan18 分钟前
marker BiBERTo解释
java·前端·人工智能
zhoumeina9926 分钟前
分段创建产品,tab 页切换又要保留缓存
前端·javascript
SilentSamsara27 分钟前
命令行工具开发:Click/Typer + 打包为独立二进制
linux·服务器·开发语言·前端·python·青少年编程·fastapi
恋猫de小郭30 分钟前
能在手机本地跑的图像生成模型 Bonsai Image ,效果还不错
前端·aigc·ai编程
Bigger31 分钟前
实战:搭建 AI Code Review 自动化流水线
前端·ci/cd·自动化运维
IT_陈寒37 分钟前
被Vite的HMR坑惨了,原来这样配置才能用对!
前端·人工智能·后端
The Sheep 202339 分钟前
EFcore 查询数据
java·javascript