用MiniMax-M2大语言模型打造浏览器插件:智能识别并自动去除网页广告

📅 发布时间:2026/10/8 17:35:38
用MiniMax-M2大语言模型打造浏览器插件:智能识别并自动去除网页广告
1. 浏览器广告拦截为什么需要大语言模型介入传统广告拦截插件的工作方式本质上是维护一张不断膨胀的规则表。EasyList、AdGuard 这类规则库动辄几万条选择器靠document.querySelectorAll批量匹配命中就隐藏或删除。这套机制在十年前够用但现在的网页广告早就变了形态类名随机化classx7f3a、广告内容由前端框架动态注入、原生广告和正文混排、iframe 嵌套三层以上。规则匹配的命中率越来越低误杀率却越来越高——我见过不少插件把评论区、推荐阅读甚至登录框一起干掉。大语言模型的介入点在于它不依赖固定规则而是理解 DOM 节点的语义。给它一段 HTML 片段、类名、文本内容、位置尺寸它能判断这看起来像广告还是像正文。MiniMax-M2 这类模型在代码和代理任务上做了专门优化能读懂网页结构也能直接生成 DOM 操作代码正好契合这个场景。这篇要交付的是一个可落地的浏览器插件方案用 MiniMax-M2 做广告节点识别用 MutationObserver 做动态监听用规则做兜底最终在真实网页上验证去广告效果。适合有基础前端能力、想尝试把大模型接进浏览器扩展的开发者。核心检索词就是 MiniMax-M2、浏览器插件、大语言模型、广告拦截、DOM 分析下面所有代码都可以直接复制运行。先说清楚边界模型只负责判断这个节点是不是广告不负责执行删除。删除动作由插件本地完成模型输出的是结构化结论。这样设计的好处是即使模型返回异常也不会破坏页面结构。另外模型调用要加缓存和批量合并否则一个页面几百个节点逐个请求延迟和成本都扛不住。2. TaoToken 前置准备拿到可用的模型调用凭证要让插件调用 MiniMax-M2先得有一个稳定的 API 入口。我这边用的是 TaoToken 平台它提供 OpenAI 兼容接口接入成本低插件里改个 baseURL 就能跑。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 根地址是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。第一步注册并创建密钥。登录后进入控制台找到 API Keys 页面deep linkhttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 新建一个 Key复制保存。这个 Key 就是插件里Authorization头的值格式是Bearer sk-xxxx。密钥只显示一次丢了只能重建。第二步确认模型 ID。在模型对话页面deep linkhttps://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 可以先手动测一下 MiniMax-M2 是否可用输入一句返回 JSON{ok:true}看返回是否正常。模型 ID 填MiniMax-M2这是插件配置里model字段的值。第三步了解接入文档。文档页deep linkhttps://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里有完整的请求格式、参数说明和错误码。重点看 chat completions 的请求体结构插件里构造 prompt 时要用到。如果你打算长期做编码类或 Agent 类项目可以看下 Coding Plandeep linkhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 按套餐走比按量计费更划算。控制台入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 用量、余额、调用记录都在这里看。这里要强调一点插件里绝对不要硬编码 Key。正确做法是把 Key 存在chrome.storage.local由用户在 popup 界面里填写插件运行时读取。硬编码的 Key 一旦插件被分发等于公开泄露。下面配置章节会给出完整的存储和读取逻辑。3. 可复制的插件配置与 DOM 识别规则这一节是核心给出三份可直接复制的配置manifest.json、模型调用配置、DOM 识别规则。路径和原文保持一致你新建一个文件夹ad-remover-extension/按下面的结构放文件即可。先看 manifest.json。Manifest V3 是当前 Chrome 的强制要求注意host_permissions要包含 TaoToken 的 API 域名否则 content script 发请求会被 CORS 拦掉。{ manifest_version: 3, name: 智能广告拦截器 (MiniMax-M2), version: 1.0.0, description: 基于 MiniMax-M2 的智能广告识别与去除插件, permissions: [activeTab, storage, scripting], host_permissions: [ https://taotoken.net/* ], background: { service_worker: background.js }, content_scripts: [ { matches: [all_urls], js: [content.js, utils/ad-detector.js, utils/dom-cleaner.js], run_at: document_end, all_frames: false } ], action: { default_popup: popup/popup.html, default_title: 智能广告拦截器 }, icons: { 16: icons/icon-16.png, 32: icons/icon-32.png, 48: icons/icon-48.png, 128: icons/icon-128.png } }接着是模型调用配置。这份配置放在utils/config.jsKey 从 storage 读不写死。baseURL 用 TaoToken 的 API 根地址模型 ID 用 MiniMax-M2。// utils/config.js const TAOTOKEN_CONFIG { baseURL: https://taotoken.net/api, model: MiniMax-M2, endpoint: /v1/chat/completions, temperature: 0.1, maxTokens: 120 }; async function getApiKey() { const data await chrome.storage.local.get([taotokenKey]); return data.taotokenKey || ; } async function buildHeaders() { const key await getApiKey(); return { Content-Type: application/json, Authorization: Bearer ${key} }; }然后是 DOM 识别规则。规则分两层第一层是快速规则用选择器和属性做初筛把明显不是广告的节点排除掉减少模型调用量第二层才是模型判断。这份规则放在utils/ad-detector.js。// utils/ad-detector.js const AD_SELECTOR_RULES [ [class*ad-], [class*ads-], [class*advert], [id*ad-], [id*ads-], [id*banner], [class*sponsor], [class*promotion], iframe[src*doubleclick], iframe[src*googlesyndication] ]; const PRESERVE_SELECTOR_RULES [ #login-modal, .user-menu, .navigation, script, style, link[relstylesheet], form input[required] ]; function isPotentialAd(element) { if (!element || element.nodeType ! 1) return false; if (PRESERVE_SELECTOR_RULES.some(s element.matches(s))) return false; return AD_SELECTOR_RULES.some(s element.matches(s)); } function buildElementContext(element) { return { html: element.outerHTML.substring(0, 800), classes: Array.from(element.classList), id: element.id, tagName: element.tagName, textContent: (element.textContent || ).substring(0, 300), position: element.getBoundingClientRect(), visible: element.offsetParent ! null }; }这三份配置组合起来插件就有了基础骨架manifest 声明权限和注入点config 管理模型调用ad-detector 做初筛和上下文构建。接下来在 content.js 里把模型判断接进去。模型判断的 prompt 要固定格式方便解析。我用的格式是让模型返回两行理由xxx和结果是/否。解析时只取结果行避免模型自由发挥导致解析失败。// content.js 片段调用模型判断 async function queryMiniMaxModel(element) { const ctx buildElementContext(element); const prompt 你是网页广告检测专家。判断以下 DOM 元素是否为广告。 元素信息 - HTML: ${ctx.html} - 类名: ${ctx.classes.join(, )} - ID: ${ctx.id} - 文本: ${ctx.textContent} - 可见: ${ctx.visible} 请按格式回答 理由简要理由 结果是/否; const headers await buildHeaders(); const resp await fetch(TAOTOKEN_CONFIG.baseURL TAOTOKEN_CONFIG.endpoint, { method: POST, headers, body: JSON.stringify({ model: TAOTOKEN_CONFIG.model, messages: [{ role: user, content: prompt }], temperature: TAOTOKEN_CONFIG.temperature, max_tokens: TAOTOKEN_CONFIG.maxTokens }) }); if (!resp.ok) throw new Error(API resp.status); const data await resp.json(); const text data.choices[0].message.content; const line text.split(\n).find(l l.startsWith(结果)); return line ? line.includes(是) : false; }到这里配置和识别规则就齐了。注意buildHeaders是异步的因为要读 storage。如果你在 content script 里直接调用确保 await 到位否则 Authorization 头会是空的直接 401。4. 验证请求与成功结果在真实网页上跑通配置写完后必须验证。验证分三步先单独测 API 通不通再测插件注入最后在真实网页上看去广告效果。第一步测 API。在浏览器控制台或 Node 里跑一段最小请求确认 Key 和模型 ID 都对。// 最小验证请求 fetch(https://taotoken.net/api/v1/chat/completions, { method: POST, headers: { Content-Type: application/json, Authorization: Bearer sk-你的Key }, body: JSON.stringify({ model: MiniMax-M2, messages: [{ role: user, content: 只回复两个字可用 }], max_tokens: 20 }) }).then(r r.json()).then(d console.log(d.choices[0].message.content));如果返回可用说明凭证和模型都没问题。如果返回 401检查 Key 是否复制完整、有没有多余空格。如果返回 404检查 baseURL 和 endpoint 拼接是否正确TaoToken 的路径是/api/v1/chat/completions。第二步加载插件。打开chrome://extensions/开启开发者模式点加载已解压的扩展程序选中ad-remover-extension/文件夹。加载成功后在插件详情里点Service Worker看后台日志点 popup 图标看界面是否正常弹出。在 popup 里填入 Key保存。第三步真实网页验证。打开一个广告较多的新闻页按 F12 看 Console。正常情况下会看到类似输出[AdRemover] 初筛命中 12 个候选节点 [AdRemover] 模型判定为广告: 7 个 [AdRemover] 已移除 7 个广告节点估算节省 48.2 KB同时页面上原本的横幅广告、侧边推广位会淡出消失。如果某些广告没被移除看 Console 里对应节点的判定理由多半是初筛规则没命中或者模型判断为否。这时候可以手动把该节点的类名加进AD_SELECTOR_RULES。验证时要注意一个现象有些广告是 iframe 嵌套的content script 默认all_frames: false不会注入到 iframe 里。如果你要处理 iframe 广告把 manifest 里改成all_frames: true但要注意跨域 iframe 的 DOM 访问限制。成功结果的标准是三条页面正常渲染不报错、广告节点被移除、正文和功能区域完好。我实测下来新闻门户类页面准确率最高社交媒体类因为动态内容多误判率会高一些建议对这类站点开白名单。5. 本篇常见错误排查接入过程中最容易踩的坑集中在认证、请求格式和解析三块。下面按真实报错逐条对照。401 Unauthorized / invalid api key。这是最高频的错误。原因通常是 Key 没读到、格式不对或已失效。排查顺序先在 popup 里确认 Key 已保存再在 Console 里打印await getApiKey()看是否为空。如果 Key 正确但仍 401检查Authorization头是不是Bearer开头中间有空格。还有一种情况是 Key 被复制时带了换行符用trim()处理一下。local proxy failed / Failed to fetch。这个报错说明请求根本没发出去通常是host_permissions没配 TaoToken 域名或者 content script 在跨域 iframe 里发请求被拦。检查 manifest 里host_permissions是否包含https://taotoken.net/*。如果是 iframe 场景考虑把请求放到 background service worker 里发content script 通过chrome.runtime.sendMessage转发。reading choices / Cannot read properties of undefined。这是解析错误说明data.choices是 undefined。原因可能是 API 返回了错误结构比如{error: {...}}但代码直接取choices[0]。修复方式是先判断data.error再取 choices。另外message.content在某些返回里可能是数组格式要做兼容。// 健壮解析 const data await resp.json(); if (data.error) throw new Error(data.error.message); const choice data.choices data.choices[0]; if (!choice) throw new Error(no choices in response); const text typeof choice.message.content string ? choice.message.content : choice.message.content.map(c c.text).join();OAuth / 认证方式混淆。有些平台用 OAuth token有些用 API Key两者不能混用。TaoToken 这里用的是 API Key直接放Authorization: Bearer。如果你之前配过 Claude Code 或 Codex 的 auth.json注意那是另一套凭证体系不要混。Codex 的 auth.json 里存的是 OAuth 凭证格式和 API Key 完全不同插件里不要读那个文件。模型返回格式不稳定。偶尔模型不按结果是/否格式返回导致解析失败。兜底方案是解析失败时走规则判断不要直接抛错。同时把 temperature 压到 0.1减少自由发挥。误杀正文。如果发现正文段落被移除检查PRESERVE_SELECTOR_RULES是否覆盖了正文容器。更稳妥的做法是模型判定为广告后再加一道尺寸校验宽度小于 200px 或高度小于 100px 的节点才移除避免大块正文被误删。缓存导致判断过期。同一个类名的节点在不同页面含义可能不同缓存 key 要用类名ID文本哈希组合不能只用类名。缓存也要设上限比如最多 500 条超出后淘汰最旧的。排查的核心思路是先确认请求发出去了没有再确认返回结构对不对最后确认解析逻辑。三步定位基本能覆盖九成问题。6. 语义一致的接入入口与后续扩展插件跑通后如果你想继续扩展比如加白名单、加统计面板、加批量扫描都可以在现有骨架上叠加。白名单逻辑放在 background 里用chrome.storage.local存域名列表content script 启动时先查白名单命中就跳过。统计面板在 popup 里读 storage 里的计数实时刷新。模型调用这块如果页面节点特别多建议上批量合并把 10 个节点的上下文拼成一个 prompt让模型一次性返回 10 个判断结果。这样能把请求数降到十分之一延迟和成本都明显下降。批量 prompt 的格式要固定比如元素1: 是/否解析时按行取。如果你要把这套方案用到更复杂的编码或 Agent 场景比如让模型直接生成 DOM 操作代码而不是只做判断可以走 Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 套餐制更适合高频调用。模型对话入口在 https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 可以随时手动测 prompt 效果。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 参数细节都在里面。API Keys 管理在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 控制台在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。最后给一个实用技巧调试阶段把max_tokens设小一点比如 60让模型只返回结果行减少解析负担。上线前再把 prompt 里的理由部分去掉进一步压缩 token。另外content script 里所有网络请求都要加 try/catch模型调用失败时静默降级到规则判断不要让插件因为一次请求失败就整个卡住。这套方案我在几个新闻站和博客站上跑过规则初筛加模型判断的组合比纯规则方案的命中率高出一截误杀也控制得住。