Chrome插件Content Script开发:页面注入与DOM操作
📅 2026/7/22 22:04:45
👁️ 阅读次数
📝 编程学习
摘要:本文详细介绍Chrome插件Content Script的开发,重点讲解页面注入机制、DOM操作方法、与Background Script通信等核心技术,并以MuxDesk的两款独立Chrome插件(Instagram视频下载器、Telegram视频下载器)为例展示实际应用。
一、引言
1.1 背景介绍
Content Script是Chrome插件中运行在网页上下文中的脚本,它可以访问和修改网页的DOM元素,是实现插件功能的核心组件之一。
产品背景:MuxDesk 目前提供两款独立的 Chrome 插件——Instagram 视频下载器和Telegram 视频下载器,分别针对各自平台做视频流检测。下文代码示例会分别展示两款插件的 Content Script 实现方式,你也可以把它们理解为同一套代码逻辑的两个独立发行版本。
1.2 本文目标
通过本文,你将了解:
- Content Script的基本概念和工作原理
- 页面注入的几种方式
- DOM操作的常用方法
- 与Background Script的通信机制
- MuxDesk的Instagram/TG插件如何使用Content Script检测视频
二、Content Script基础
2.1 什么是Content Script?
Content Script是运行在网页上下文中的JavaScript脚本,具有以下特点:
- 可以访问网页的DOM
- 可以读取网页内容
- 可以修改网页样式
- 与Background Script隔离
2.2 配置方式
// manifest.json(以 MuxDesk Instagram 视频下载器为例){"content_scripts":[{"matches":["https://www.instagram.com/*"],"js":["content.js"],"css":["content.css"],"run_at":"document_idle"}]}最佳实践:
matches应精确限定到目标站点域名,而不是用<all_urls>全站注入。MuxDesk 的 Instagram 插件只匹配instagram.com,Telegram 插件只匹配t.me/web.telegram.org,既减少性能开销,也降低隐私风险。
2.3 注入时机
document_start:DOM加载前document_end:DOM加载完成document_idle:页面加载完成后(推荐)
三、页面注入方式
3.1 静态注入
{"content_scripts":[{"matches":["https://www.instagram.com/*"],"js":["content.js"],"run_at":"document_idle"}]}3.2 动态注入
// 使用scripting API动态注入chrome.scripting.executeScript({target:{tabId:tabId},files:['content.js']});3.3 注入CSS
// 动态注入CSSchrome.scripting.insertCSS({target:{tabId:tabId},files:['content.css']});四、DOM操作基础
4.1 查询元素
// 通过ID查询constelement=document.getElementById('myId');// 通过类名查询constelements=document.getElementsByClassName('myClass');// 通过标签名查询constvideos=document.getElementsByTagName('video');// 通过CSS选择器查询constelement=document.querySelector('.my-class');constelements=document.querySelectorAll('.my-class');4.2 修改元素
// 修改文本内容element.textContent='New text';// 修改HTML内容element.innerHTML='<strong>Bold text</strong>';// 修改属性element.setAttribute('src','new-image.jpg');// 修改样式element.style.color='red';element.style.display='none';4.3 创建和删除元素
// 创建新元素constnewElement=document.createElement('div');newElement.textContent='Hello World';document.body.appendChild(newElement);// 删除元素element.remove();五、MuxDesk的Content Script实现
5.1 视频检测器
// MuxDesk Content Script - 视频检测classVideoDetector{constructor(){this.videos=[];this.observer=null;}init(){// 初始检测this.detectVideos();// 监听DOM变化this.observer=newMutationObserver(()=>{this.detectVideos();});this.observer.observe(document.body,{childList:true,subtree:true});}detectVideos(){// 检测video标签constvideoElements=document.querySelectorAll('video');videoElements.forEach(video=>{if(video.src&&!this.videos.includes(video.src)){this.videos.push(video.src);this.notifyBackground(video.src);}});// 检测source标签constsourceElements=document.querySelectorAll('source');sourceElements.forEach(source=>{if(source.src&&!this.videos.includes(source.src)){this.videos.push(source.src);this.notifyBackground(source.src);}});}notifyBackground(url){chrome.runtime.sendMessage({action:'videoDetected',url:url});}}// 初始化constdetector=newVideoDetector();detector.init();5.2 DOM监听器
// DOM变化监听classDOMWatcher{constructor(){this.observer=null;}start(){this.observer=newMutationObserver((mutations)=>{mutations.forEach(mutation=>{// 处理新增节点mutation.addedNodes.forEach(node=>{if(node.nodeType===Node.ELEMENT_NODE){this.processNode(node);}});});});this.observer.observe(document.body,{childList:true,subtree:true,attributes:true,attributeFilter:['src','href']});}processNode(node){// 检查是否是视频元素if(node.tagName==='VIDEO'||node.tagName==='SOURCE'){console.log('Video element detected:',node);}// 检查子元素constvideos=node.querySelectorAll('video, source');videos.forEach(video=>{console.log('Video element detected:',video);});}stop(){if(this.observer){this.observer.disconnect();}}}5.3 消息通信
// 与Background Script通信classMessageHandler{constructor(){this.init();}init(){// 监听来自Background的消息chrome.runtime.onMessage.addListener((request,sender,sendResponse)=>{console.log('Received message:',request);switch(request.action){case'startDetection':this.startDetection();sendResponse({status:'started'});break;case'stopDetection':this.stopDetection();sendResponse({status:'stopped'});break;case'getVideos':sendResponse({videos:this.getVideos()});break;}returntrue;});}sendToBackground(message){chrome.runtime.sendMessage(message,(response)=>{console.log('Response from background:',response);});}startDetection(){// 开始检测逻辑}stopDetection(){// 停止检测逻辑}getVideos(){// 获取检测到的视频return[];}}六、平台特定实现
6.1 Instagram视频检测
// Instagram视频检测classInstagramDetectorextendsVideoDetector{detectVideos(){// 检测Reelsconstreels=document.querySelectorAll('article video');reels.forEach(video=>{this.processVideo(video,'reel');});// 检测Storiesconststories=document.querySelectorAll('story video');stories.forEach(video=>{this.processVideo(video,'story');});// 检测帖子视频constposts=document.querySelectorAll('article video');posts.forEach(video=>{this.processVideo(video,'post');});}processVideo(video,type){constinfo={url:video.src||video.currentSrc,type:type,duration:video.duration,width:video.videoWidth,height:video.videoHeight};console.log('Instagram video detected:',info);this.notifyBackground(info);}}6.2 Telegram视频检测
// Telegram视频检测classTelegramDetectorextendsVideoDetector{detectVideos(){// 检测消息中的视频constmessages=document.querySelectorAll('.message');messages.forEach(message=>{constvideo=message.querySelector('video');if(video){this.processVideo(video,message);}});}processVideo(video,message){constinfo={url:video.src||video.currentSrc,messageId:message.dataset.messageId,duration:video.duration};console.log('Telegram video detected:',info);this.notifyBackground(info);}}七、常见问题
7.1 问题一:Content Script无法访问DOM
现象:Content Script中查询DOM返回null
原因:注入时机过早,DOM未加载完成
解决:
// 等待DOM加载完成if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',init);}else{init();}7.2 问题二:Content Script与Background通信失败
现象:发送消息后没有收到响应
原因:Service Worker未启动或已休眠
解决:
// 发送消息前检查Service Worker状态asyncfunctionsendMessage(message){try{constresponse=awaitchrome.runtime.sendMessage(message);returnresponse;}catch(error){console.error('Send message failed:',error);}}7.3 问题三:DOM监听器性能问题
现象:页面卡顿,CPU占用高
原因:MutationObserver监听范围过大
解决:
// 限制监听范围observer.observe(targetNode,{childList:true,subtree:false,// 不监听子树attributes:false});八、总结
8.1 核心要点
- Content Script运行在网页上下文中
- 可以访问和修改网页DOM
- 使用MutationObserver监听DOM变化
- 通过消息机制与Background Script通信
8.2 最佳实践
- 选择合适的注入时机
- 限制DOM监听范围
- 处理异步操作
- 注意性能优化
九、参考资料
- Chrome Extension Documentation
- Content Scripts Reference
- MuxDesk官网
相关推荐:
- Chrome插件开发入门:Manifest V3基础架构详解
编程学习
技术分享
实战经验