| 方案 | 可行性 | 缺點 |
| 腳本阻擋插件 | ❌ | 內聯腳本無法攔截,破壞頁面功能 |
| 禁用 JS | ❌ | 導致頁面無法渲染/交互 |
| Chrome Extension + API Hook | ✅ | 需開發擴展,但最徹底 |
插件架構:Manifest V2
{
"name": "UnBlock Copy",
"manifest_version": 2,
"version": "1.0.0",
"description": "解除網頁複製限制",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [{
"matches": ["https://*/*", "https://*/*"],
"js": ["js/hookapi.js"],
"run_at": "document_end",
"all_frames": true
}]
}
核心 Hook 腳本:hookapi.js
// 需要解除綁定的事件列表
const events = [
'oncontextmenu', 'ondragstart', 'onselectstart',
'onselect', 'onbeforecopy', 'oncopy'
];
// 保存原始屬性描述符
const originalDescriptors = new Map();
function hookEvent(eventName) {
const descriptor = Object.getOwnPropertyDescriptor(Document.prototype, eventName) ||
Object.getOwnPropertyDescriptor(HTMLElement.prototype, eventName) ||
Object.getOwnPropertyDescriptor(Element.prototype, eventName) ||
Object.getOwnPropertyDescriptor(Node.prototype, eventName);
if (!descriptor) return;
originalDescriptors.set(eventName, descriptor);
// 重新定義屬性:setter 直接忽略賦值
Object.defineProperty(document.body, eventName, {
set: function(val) { /* 吞掉賦值,不綁定任何處理器 */ },
get: function() { return null; },
configurable: true
});
}
// 執行 Hook
events.forEach(hookEvent);
// 額外:移除已綁定的屬性(針對內聯腳本已執行的情況)
events.forEach(e => document.body[e] = null);
關鍵技術點
- 原型鏈查找:事件屬性可能定義在 Document/HTMLElement/Element/Node 上,需逐級查找
- Object.defineProperty:攔截 setter,阻止賦值生效
- run_at: document_end:確保在頁面腳本執行前/中注入,但內聯腳本可能已執行,故需額外清空
body[event]=null
- all_frames: true:覆蓋 iframe 內頁面
安裝測試流程
- Chrome 打開
chrome://extensions/
- 開啟「開發者模式」
- 點擊「加載已解壓的擴展程序」,選擇插件目錄
- 測試目標網站:右鍵、選擇、複製應恢復正常
進階:Manifest V3 遷移
MV3 中 content_scripts 機制不變,但需注意 host_permissions 聲明。核心 Hook 邏輯不變。
道德與法律提示
此技術僅供學習瀏覽器擴展開發與 JS 原型鏈機制理解,請尊重網站版權與服務條款,勿用於非法內容獲取。
- 上一篇文章: HDU 4966 最小樹形圖:課程等級依賴建模與朱劉算法
- 下一篇文章: Cocos2d-x PhysicsBody 解析器:從 Physics Body Editor JSON 載入多邊形碰撞體
Copyright ©
程式碼之家 All Rights Reserved