豆包 AI 生图去水印插件(MDX 视觉版)

2026年6月29日MDX浏览器扩展谷歌插件豆包AI图片

Browser Extension

不擦图,只替换成页面已经拿到的原图

这个插件的重点不是图像算法,而是在豆包页面运行时捕获接口里的签名原图地址,再把预览和下载链路里的水印 URL 替换掉。

水印模板原图模板
image_dld_watermarkimage_raw

关键约束:ByteImage URL 的签名和路径绑定,不能靠删除字符串猜原图。

这个插件解决什么问题

豆包 AI 生图页面在展示和下载图片时,有些场景会使用带水印的图片地址。但在页面接口数据里,同一张图片有时也会出现已经签名的原图地址。

这个插件的思路不是做图像修复,也不是用算法擦掉图片上的水印,而是在页面运行时优先使用接口里已经返回的原图 URL。它只在 https://www.doubao.com/* 生效,不上传图片,也不请求第三方服务。

这个边界很重要:扩展做的是本地页面 URL 替换,不是重新生成图片,也不是绕过一个外部图片处理服务。

先找数据源

从接口返回值里收集真实存在的 signed URL,而不是猜测图片地址。

再做映射

用图片主体文件名作为 key,把多个水印模板统一指向原图模板。

最后同步页面

接口拦截负责拿到原始数据,DOM 监听负责处理已经渲染出来的内容。

一开始最容易误判的地方

看到图片 URL 里有 watermark 模板后缀时,很容易以为把这段路径删掉就能得到原图。

实际不行。豆包图片资源使用的是带签名的 ByteImage URL,x-signature 和完整路径绑定。如果把路径里的水印模板直接删掉,原来的签名就不再匹配,请求会返回 403

所以这个插件不能靠猜 URL。正确做法是从页面接口返回值里收集真实存在、已经签好名的 image_raw 原图地址,再用它替换同一张图片对应的水印地址。

核心映射关系

接口里同一张图片通常会出现多个模板版本。它们的主体文件名相同,例如都属于同一个 rc_gen_image/<filename>,但后面的模板不同:

  • image_raw 表示原图模板。
  • image_pre_watermark 更偏页面预览。
  • image_dld_watermark 更偏下载。
  • downsize_watermarkhcg_watermarkimg_pre_mark 也是需要识别的水印变体。

插件用图片主体文件名作为 key,建立这样的映射:

rc_gen_image/<filename> -> 已签名的 image_raw URL

后续只要看到同一个 key 的水印 URL,就可以替换成之前记录下来的原图 URL。

看到页面 URL

rc_gen_image/demo~tplv-image_dld_watermark

替换为原图 URL

rc_gen_image/demo~tplv-image_raw

为什么逻辑要运行在页面上下文

这个项目里 Content Script 只负责尽早注入 pageScript.js,真正的拦截逻辑运行在网页上下文中。

原因是浏览器扩展的 Content Script 和页面自己的 JavaScript 是隔离的。如果要改写页面里的 JSON.parsefetchXMLHttpRequest.open,逻辑必须进入页面上下文,否则只能看到一部分 DOM,拿不到最早的接口数据。

插件在页面里做了几件事:

  1. patch JSON.parse,在接口 JSON 被页面消费前扫描图片字段。
  2. patch fetchXMLHttpRequest.open,尽量覆盖不同请求路径。
  3. 递归遍历接口对象,先收集原图 URL,再替换水印 URL。
  4. 观察 DOM,把已经渲染出来或后续新增的 img.srca.href 同步清理。

这里的关键不是只拦截网络,也不是只扫 DOM,而是两者都做。接口数据能拿到更完整的原图信息,DOM 扫描则负责补上已经显示出来的内容。

开关状态要跨上下文同步

扩展默认启用,但用户应该能随时关闭。开关状态保存在 browser.storage.local,popup 修改状态后,Content Script 会把状态同步给页面脚本。

这个设计里有一个细节:关闭时不能只是把变量设成 false,还要恢复被 patch 的原生方法,停止 DOM 监听,避免页面一直被扩展影响。重新开启时再安装 hooks,并给出简短状态提示。

这种可恢复的设计比“刷新页面后生效”更友好,也更容易排查问题。

这个方案的风险

这个插件依赖豆包页面内部接口字段和图片 URL 模板。只要页面改版、接口字段调整、模板命名变化,识别规则就可能失效。

所以代码里把原图模板、水印模板、图片 key 提取规则集中处理。未来维护时可以先抓包确认新的 URL 规律,再更新规则,而不是在整个项目里到处找字符串。

另外,浏览器扩展运行在第三方页面上,也要控制权限范围。当前只声明豆包域名和必要的存储权限,减少无关页面的影响面。

Takeaway

先确认数据来源,再写替换逻辑。

如果没有先弄清签名 URL 的规则,很容易把时间花在清理字符串上。更稳定的做法是尊重页面已经拿到的数据,只替换成真实存在的 signed URL。

做完后的经验

这个插件的核心经验是:先确认数据来源,再写替换逻辑。

如果没有先弄清楚签名 URL 的规则,很容易把时间花在“清理 URL 字符串”上,最后得到一堆 403。真正稳定的做法是尊重页面已经拿到的数据,只替换成接口中真实存在的 signed URL。

另一个经验是,把浏览器扩展当成一个运行在复杂宿主页面里的小系统。它需要安装、卸载、同步状态、处理页面动态更新,还要尽量在目标网站变化时保留可维护性。

这个项目看起来是在处理图片 URL,实际更像是在练习:如何在不控制宿主页面的情况下,把一个小功能做得足够克制、可关闭、可维护。

花不卷花不卷

© 2026 sharpmind.tech All rights reserved.

XGitHub