ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

零成本打造AI网页翻译插件:油猴脚本+大模型API实战指南

零成本打造AI网页翻译插件:油猴脚本+大模型API实战指南 1. 项目概述1.1 零成本建翻译插件的核心思路我这段时间一直在折腾一件事不花一分钱给自己搞一个顺手的网页翻译工具。起因很简单日常看技术文档、读英文论文、刷开源项目 README总得在浏览器和翻译软件之间来回切换复制粘贴太烦了。市面上现成的翻译插件确实不少但要么有字数限制要么需要注册账号要么用起来总觉得不够“自己的味道”。正好大模型 API 的热度一路走高DeepSeek、智谱这些厂商都在推免费额度DeepSeek 的新用户甚至直接送了几百万 token。我的想法很直接既然大模型翻译质量比传统机翻好一大截免费 API 额度又够用为什么不能自己用油猴脚本或者浏览器扩展把这些能力包成一个翻译插件这个项目本质上是三件事的拼装一个能触发翻译的浏览器脚本、一个调用大模型 API 的后端逻辑、一个把译文回填到网页里的渲染方案。听起来简单做起来也确实不算难但细节里坑不少尤其是 API 鉴权、跨域请求、DOM 节点替换这几块我踩了一路的雷今天一并整理出来。适合谁参考想动手折腾 AI 工具但不想花钱买会员的朋友前端刚入门想练练手的新人或者单纯觉得现成翻译插件不够好用、想定制一个符合自己阅读习惯的译者。我会把从选型到上线、再到排查问题的全部过程写清楚你照着做就能复现。1.2 老翻译插件的问题在哪里先聊聊我为什么非自己造轮子不可。市面上主流的翻译插件核心痛点其实不是翻译质量而是“流程割裂”。你装了一个插件点一下翻译它把整个页面变成双语对照或者干脆替换成纯译文然后你想看英文原句还得再点一下切换。阅读过程中中英文来回横跳思路经常断。更现实的问题是成本和质量不对等。免费翻译服务比如各家网页翻译虽然不花钱但翻译专业术语时经常生硬得让人头大付费 API 又按字符计费长文档翻译一次可能烧掉不少钱。而大模型 API 的免费额度把这些事情变成了可能——DeepSeek 的免费额度我实测下来翻译几百篇技术文档都用不完。还有一个让很多人忽略的点隐私。网页翻译要把整个页面内容发送给翻译服务商。用大厂公共翻译接口等于把你在看的每一篇文档都交给对方。自建插件 免费大模型 API虽然也不是完全本地化但至少链路是自己可控的数据去向更透明心里踏实不少。2. 技术选型与方案权衡2.1 为什么最终选定油猴脚本 大模型 API最开始我纠结过两条路线正经做浏览器扩展Manifest V3还是搞油猴脚本。浏览器扩展的优势很明确权限体系完整、可以后台运行、UI 可以做得精致。但劣势同样扎心——发布到 Chrome 应用商店要交 5 美元注册费而且 Manifest V3 对远程代码限制非常严格每次改逻辑都得走审核。自己本地加载未打包扩展虽然免费但每次打开浏览器都会提示“请停用以开发者模式运行的扩展程序”体验很割裂。油猴脚本Tampermonkey / Violentmonkey就不一样了。它本质上是一个用户脚本管理容器脚本以纯 JavaScript 形式分发改完刷新页面就能生效不需要任何注册费也没有加载未打包扩展的提示。对于翻译这种纯前端交互场景油猴脚本的 API 足够用GM_xmlhttpRequest 还能绕过跨域限制直接请求大模型 API简直是为这个需求量身定做的。大模型 API 这边我的筛选标准是三条有免费额度且够用、上下文窗口不要太抠门、API 风格对开发者友好。综合下来DeepSeek-V3 和智谱 GLM 系列是首选。DeepSeek 的免费 token 额度大智谱的 GLM-4-Flash 干脆就是永久免费的两者都是 OpenAI 兼容的接口格式代码写一次换厂商就换一个 Base URL 的事。2.2 免费大模型 API 选型对比我实测对比了目前主流的几家免费/低价 API列个表给大家参考厂商模型名免费额度上下文窗口接口风格DeepSeekdeepseek-chat注册赠送数百万 token64K~128KOpenAI 兼容智谱 AIglm-4-flash永久免费128KOpenAI 兼容硅基流动Qwen2.5-7B 等注册赠额度32KOpenAI 兼容Moonshotmoonshot-v1-8k注册赠额度8KOpenAI 兼容选型逻辑很直白。翻译任务依赖的是语义理解和上下文连贯模型参数量太小的免费模型比如 7B 以下长段翻译时容易出现句子断裂、术语前后不一致的问题。DeepSeek 和智谱这些模型在中文上的表现明显更好因为它们的中文训练语料占比高对于中英翻译的语序调整、长句拆分处理得更自然。接口风格统一用 OpenAI 兼容格式是为了降低后期切换成本。你不想被某一家厂商绑定一辈子也不想每次换 API 都要重写大段请求逻辑。OpenAI 兼容的 Chat Completions 接口请求体结构基本是固定的 messages 数组 model 字段只有 Base URL 和 API Key 不同。脚本里把这两项抽成配置换模型就是改配置的事。2.3 自建插件相比现有插件的优势这个方案的竞争力体现在三个维度。第一是零成本。市面上一款靠谱的 AI 翻译插件会员费一年少说几百块。自建方案用的是免费 API 额度而且就算额度用完了充值成本也远低于订阅制会员——DeepSeek 的 API 价格我记得是百万 token 才几块钱翻译一篇万字长文的花费大概是一厘钱级别几乎可以忽略不计。第二是可控性强。你可以完全决定翻译的触发方式、提示词策略、译文展示形式。比如我在脚本里写了一个小功能鼠标选中一段英文按快捷键 AltT 就只翻译选中的部分弹出一个小气泡显示译文。这种交互细节现成插件基本不会给你做但你可以在自己的脚本里随意实现。第三个优势是“直觉级”隐私掌控。自建之后你清楚知道每一段文本发往哪里、被谁处理了。想彻底离线就用本地模型部署想兼顾效果就用云端免费 API。这种掌控感用现成工具是体会不到的。3. 从零搭建翻译插件的完整流程3.1 注册 API Key 与配置环境第一步拿到大模型 API 的访问凭证。以 DeepSeek 为例打开官网注册账号进入控制台创建一个 API Key。创建时注意 Key 只显示一次务必立刻复制保存丢了就得重新生成。智谱 AI 的流程类似它的开放平台里有专门的 API Key 管理页面。拿到 Key 之后不要直接硬编码在脚本里这一点很重要。油猴脚本是明文 JavaScript任何人打开你的脚本都能看到内容。如果你把 Key 写死在脚本里再传到一个公开的脚本分享站这 Key 基本就相当于公之于众了。我的做法是利用油猴脚本的 GM_registerMenuCommand 做一个设置面板Key 存在 localStorage 里既不用每次写死也不会在代码里泄露。配置环境这块油猴脚本本身不需要“安装环境”浏览器装好 Tampermonkey 扩展就行。这里有个小建议用 Violentmonkey 替代 Tampermonkey 也完全可以它在开源社区里维护更活跃对 GM_xmlhttpRequest 的实现也更干净。两者的 API 基本互通下面代码在任一环境都能跑。3.2 核心代码实现请求、翻译与回填整个脚本的骨架分四个部分配置管理、翻译请求、DOM 文本提取、译文渲染。我直接给出精简版核心代码你可以在自己的脚本里扩展// UserScript // name 网页智能翻译 // namespace translator // version 0.1.0 // description 调用免费大模型 API 翻译网页内容的油猴脚本 // match *://*/* // grant GM_xmlhttpRequest // grant GM_registerMenuCommand // grant GM_getValue // grant GM_setValue // /UserScript const CONFIG { apiBase: https://api.deepseek.com/v1/chat/completions, model: deepseek-chat, apiKey: , targetLang: 中文, maxTextLength: 6000 }; // 初始化配置与设置菜单 function initConfig() { CONFIG.apiKey GM_getValue(apiKey, ); GM_registerMenuCommand(设置 API Key, () { const key prompt(请输入你的 API Key); if (key) { GM_setValue(apiKey, key.trim()); CONFIG.apiKey key.trim(); } }); } // 调用大模型翻译 function translateText(text, onSuccess, onError) { const prompt 你是一位专业的翻译引擎。请将以下内容翻译为${CONFIG.targetLang}。\n只输出翻译结果不要任何解释。\n\n内容\n${text}; GM_xmlhttpRequest({ method: POST, url: CONFIG.apiBase, headers: { Content-Type: application/json, Authorization: Bearer ${CONFIG.apiKey} }, data: JSON.stringify({ model: CONFIG.model, messages: [ { role: system, content: You are a professional translator. }, { role: user, content: prompt } ], temperature: 0.3, stream: false }), onload: (res) { if (res.status 200) { const result JSON.parse(res.responseText); onSuccess(result.choices[0].message.content.trim()); } else { onError(请求失败状态码${res.status}); } }, onerror: (err) onError(请求发生网络错误) }); }这段代码核心就两个动作构造 prompt发送请求。temperature: 0.3是翻译任务的一个关键参数——翻译需要忠实原意随机性太高会导致翻译结果不稳定同样的句子翻两次说法不一样。0.2 到 0.4 之间是比较稳妥的区间。如果你的 API 支持temperature且默认值偏高一定要显式压低。3.3 让脚本识别网页正文并实现翻译替换拿到译文之后最麻烦的问题是“怎么把译文放回正确的位置”。整页翻译和选中翻译是两种不同的 DOM 操作策略。整页翻译的贪心做法是把document.body.innerText全量发给大模型让它整页翻完再把 body 的 HTML 替换掉。这种做法最大的副作用是网页结构几乎全毁样式、事件绑定全都没了原文和译文也没有对照关系。实际体验很糟糕。更好的方案是按块翻译。遍历 body 下的文本节点把连续的短文本节点合并成逻辑段落逐段调用 API。这样做的好处是译文回填时只替换对应文本节点的textContent样式完全不动阴影、布局都保留。代价是 API 请求次数变多翻译长文时需要排队请求速度慢一些。我最终用的是折中方案把单个文本节点长度超过 60 字符的优先处理短文本合并成组再请求这样既减少请求次数又能保持页面结构。用户界面交互上我做了一个悬浮球。右下角一个小圆钮点一下弹出操作面板整页翻译、恢复原文、选中翻译三个按钮。恢复原文的思路是在翻译前先把整个 body 的 innerHTML 快照存到变量里想还原就document.body.innerHTML snapshot。选中翻译则监听鼠标松开事件读取window.getSelection().toString()把选中文本送去翻译译文用临时气泡展示。这里有一个极其重要的细节翻译替换时一定要用textContent而不是innerHTML。网页里的文本节点有些包含嵌套标签直接改 innerHTML 会把译文中的尖括号、特殊字符当作 HTML 解析轻则译文显示错乱重则直接破坏页面结构。我第一次写的时候就在这里翻过车翻译一个包含div字样代码示例的页面结果整页布局直接崩了。3.4 界面改造与交互体验打磨翻译插件的 UI 不需要多复杂但也不能丑到影响使用。我的设计是右下角一个 40x40 的圆形按钮半透明毛玻璃质感悬浮在所有页面之上。这个按钮用 fixed 定位z-index 设为 2147483647油猴脚本常用最大级确保任何页面上都能看到、点到。点击按钮弹出操作面板面板里除了三个功能按钮还要显示当前的 API 配置摘要和剩余请求状态。我这里没有做配额查询因为各厂商的配额查询接口差异较大写通用代码收益不高。如果你想加可以针对自己用的厂商单独实现一个余额查询函数展示在面板里。图标可以用简单的 SVG 内联不需要引入外部图片资源。整页翻译按钮点击后按钮颜色变为橙色并显示“翻译中”所有请求结束后恢复原样。这样用户能直观感知任务是否进行中。我实测翻译一篇含 30 个文本块的长文请求耗时大约 20 到 40 秒如果不做状态反馈用户很可能以为脚本卡住了。操作面板的样式我用GM_addStyle注入这样不会污染页面的原有样式体系。所有按钮确认一次点击只触发一次翻译防止用户连点导致 API 请求堆积浪费额度还容易触发厂商限流。4. 常见问题与排障手册4.1 API 请求报错的排查思路翻译脚本最大的不稳定因素就是 API 调用我把高频报错整理成了速查表报错信息原因解决办法401 UnauthorizedAPI Key 错误或过期检查 Key 是否复制完整注意别带多余空格403 Forbidden账户被风控或额度用尽登录控制台查看配额确认没有触发滥用规则400 Bad Request请求参数格式不正确检查 JSON 结构确认 model 字段名与厂商文档一致429 Too Many Requests请求过于频繁在脚本里加个简单的并发限流比如每次请求间隔 500mscontext length exceeded单次输入超长降低 maxTextLength 配置或把长文本切成多段分批翻译Debug 技巧所有 GM_xmlhttpRequest 的响应在 onload 里都能拿到打印res.responseText能看到完整错误信息。很多厂商在返回体里会写清楚具体是哪个字段出问题排查效率高很多。我在脚本里加了一个隐藏的日志面板把最近的 API 返回体都记录在里面出问题时按 CtrlShiftL 就能快速调出查看。网络错误也不容忽视。有些网页的 CSP内容安全策略策略比较严格可能会阻止油猴脚本发起的请求。不过 GM_xmlhttpRequest 在油猴中跑在独立的沙箱环境里绝大多数情况下能绕过 CSP 限制只在极少数的暴力 CORP 策略下才会被拦这种情况只能换浏览器尝试。4.2 翻译质量不理想的优化技巧免费模型和头部商业模型在翻译质量上有差距这是客观事实。但通过 prompt 优化和参数调整这个差距能缩小到可用范围内。我实践的优化方案有这几条第一在 system prompt 里写明“你是专业译者擅长科技文档翻译”能显著提升术语翻译的准确度。第二用 few-shot 示例引导格式——在 prompt 中给出一个英译中的例子对模型会照着格式输出翻译的语序和用词会顺畅很多。第三temperature固定为 0.2~0.3上面说过了这是翻译稳定性的生命线。还有一个容易被忽略的点不要翻译“空的”文本。有些文本节点的内容只是空格、换行符、标签残片发给 API 纯属浪费额度。在提取文本时做一个净化预处理过滤掉长度小于 2 且没有任何字母数字的内容。具体代码就三行function isMeaningfulText(text) { return text text.trim().length 2 /[a-zA-Z0-9\u4e00-\u9fa5]/.test(text); }4.3 页面样式错乱与被反爬识别翻译回填后页面 CSS 错乱最常见的原因是网页用了:lang()选择器或字体族设置中文译文的渲染和原文不同。解决办法在注入的样式中显式覆盖字体族比如font-family: system-ui, -apple-system, PingFang SC, Microsoft YaHei, sans-serif;中文支持基本都有。被反爬识别这个坑比较冷门但值得注意。少数网站会监测页面文本变化一旦检测到 DOM 被大规模改写就弹出人机验证或直接封会话。遇到这种站点我的建议是别硬刚干脆放弃整页翻译只保留选中翻译和阅读模式翻译两种交互降低被检测到的频率。毕竟一个脚本工具没必要跟网站的防护机制死磕。另外有些网站用的是 Canvas 字体内嵌文本文本节点存在内部状态里textContent改了界面不变。这种没法用简单办法处理碰到了随手记一下站点名单绕过去就行别在这上面浪费时间。5. 进阶玩法与扩展方向5.1 一键接入本地大模型实现完全离线翻译免费 API 用着确实香但对数据敏感的场景总归还是觉得云端兜底不稳妥。近一年本地大模型部署的门槛降了很多Ollama 一条命令就能拉起 Qwen2.5、Llama 3 这些开源模型我的 16G 内存笔记本跑 7B 量化模型翻译速度大概是每秒 15 到 25 个 token虽说不算快但配合阅读节奏刚好够用。接入方式比你想的简单。本地 Ollama 默认监听 11434 端口接口也是 OpenAI 兼容格式。脚本里只需要把apiBase换成http://127.0.0.1:11434/v1/chat/completionsmodel改成本地模型名API Key 随便填个占位符比如ollama整个逻辑不用改一行代码。实测下来7B 量化模型的翻译质量在简单的说明文档、代码注释场景已经相当能打但在复杂的文学文本、俚语表达上明显不如云端大模型需要有所预期。这种“云端免费 API 本地模型热切换”的架构是我比较推荐的组合方式。日常查阅资料用云端翻译敏感文档时一键切本地两种模式共用一个 UI体验一致数据流向完全可控。5.2 增加术语库与自定义翻译风格翻译技术文档时最头疼的是术语不一致。同一个词上一段翻译成“接口”下一段翻译成“API”阅读时很割裂。大模型本身能根据上下文保持一致但在跨页面的多次翻译中缺乏记忆能力。想要更强的术语一致性可以在 prompt 里注入术语表。在脚本配置里加一个 JSON 字段记录你常用的中英对照词条每次请求前把术语表拼进 system prompt。实际效果我测试过翻译同一篇文档带术语表的版本术语一致率能提高 40% 以上。知识库文件太长可以单独存成 Markdown 格式翻译前动态读取并截取前若干条加入 prompt注意上下文窗口别撑爆。自定义风格也是同理。有些人喜欢译文简短干练有人喜欢保留原文结构这些偏好都可以通过改 prompt 表达。我琢磨出一个通用模板翻译时遵循以下规则 1. 术语按术语表翻译未收录的专有名词保留英文 2. 译文力求通顺避免机器翻译的僵化语序 3. 代码块、变量名、URL 保持原样不翻译 4. 保持原文的段落结构和标点习惯把这些规则拼接进 system message模型就能按你的口味来。而且每个用户完全可以维护一份属于自己的“翻译规范”这种定制程度是现成工具给不了的。5.3 从油猴脚本升级为浏览器扩展当你把脚本调到顺手、功能也稳定了想发布给更多人用油猴脚本的分发渠道是有限的。虽然 GreasyFork 可以发布脚本但普通用户装起来总得多一步“安装插件管理器”传播门槛偏高。此时可以考虑把它封装成 Manifest V3 的浏览器扩展。升级核心是把 GM_xmlhttpRequest 替换为后台 service worker 的fetch油猴 API 换成 Chrome API。好消息是翻译核心逻辑和 DOM 处理部分可以 90% 复用只要把接口适配层重写一遍即可。MV3 的权限申请要注意跨域请求需要声明host_permissions需要明确的域名列表。如果只想针对特定站点翻译这个列表可以大幅收敛浏览器商店审核也更容易过。实际上我在把脚本打包成扩展的过程中最大的工作量不是代码改造而是被商店审核折腾——隐私政策、图标素材、权限说明都要准备齐全。如果是自用或者小圈子分发油猴脚本的轻便优势明显想大规模发布扩展的正式感更合适。两条路互为补充看你的具体诉求。6. 实操过程中的独家心得做到最后我把这段时间折腾的核心教训浓缩成几件事供你少走弯路。第一件事一定要先想清楚你要“整页翻译”还是“段落翻译”再动手写代码。我一开始贪心做整页百分百翻译效果结果被各种奇怪的布局问题折磨了两天后来降到按文本块翻译效率和稳定性都大幅提升。大部分阅读场景我们只需要理解每一段的含义并不需要一个“完全中文版页面”。第二件事免费 API 不等于无限额度请求策略要克制。我没做任何限流的时候一次手滑触发了整个页面的文本节点全量翻译分钟级就把一天试用额度的四分之一耗完了。后来加了防抖、去重、暂停按钮之后额度消耗速度降了一个数量级。省着用才是零成本的正确打开方式。第三件事prompt 工程在这个项目里比任何代码优化都重要。同样的模型、同样的 API一个精心设计的 prompt 和一个随手写的 prompt翻译效果可以天差地别。多花点时间打磨措辞、测试不同写法性价比远高于折腾更复杂的脚本逻辑。最后想说的是这个项目最大的价值不只是省了钱而是让我重新理解了“工具”这个词——它不再是一个固定的、别人定义好功能的商品而是可以被任何人按需裁剪、组合、改造的数字积木。API 是积木脚本是积木模型也是积木。虽然这一路踩了不少坑但当你亲手把一个只服务于你自己的翻译工具跑起来那种“一切尽在掌握”的感觉是花钱买现成工具永远体会不到的。你要不要也试一把
返回列表