豆包AI生图去水印脚本解析:从技术实现到用户体验优化 复制直接可用的油猴脚本豆包去水印

水印问题的本质与解决思路

豆包AI生成图片时,平台会在图片上添加水印,这是行业内常见的做法。但通过分析前端数据流,发现一个有趣的现象:服务器返回的JSON数据中,实际上同时包含了无水印的原图URL和有水印的URL。前端界面默认展示和下载的是带水印版本,但原始数据已经悄然抵达浏览器环境。

这一发现成为了解决问题的关键。与其费力地处理已生成的图片水印,不如在数据流动过程中进行干预,将前端默认使用的水印URL替换为无水印原图URL。这种思路类似于在物流配送中心更换包裹内容,而非在包裹送达后费力拆解。

脚本核心技术解析

该脚本的实现主要依赖几个关键技术点,这些代码设计展现了一种深度介入前端数据流的能力。

JSON.parse钩子:拦截数据流

脚本最核心的部分是重写了浏览器原生的JSON.parse方法,这是一种经典的钩子技术。通过保存原始JSON.parse引用,然后将其替换为自定义函数,脚本得以在数据解析阶段介入:

javascript 复制代码
let _parse = JSON.parse;
JSON.parse = function(data) {
  let jsonData = _parse(data);
  // ...数据处理逻辑
  return jsonData;
}

这种实现方式确保了脚本不会破坏原有的JSON解析功能,只是在解析前后添加了自定义逻辑。每当豆包前端代码调用JSON.parse解析服务器返回的数据时,我们的替换函数就会率先获得处理机会。

递归搜索算法:精准定位目标数据

脚本中的findAllKeysInJson函数采用递归算法,能够遍历整个JSON对象,无论数据结构嵌套多深,都能准确找出所有包含图片信息的"creations"字段。这种深度搜索确保了即使豆包前端数据结构发生变化,只要保留creations字段,脚本就能继续生效。

递归算法的设计值得细究:它首先检查当前对象是否包含目标键,如果找到就将对应值存入结果数组。然后继续遍历对象的每个属性或数组的每个元素,确保不遗漏任何嵌套层级中的数据。

URL替换逻辑:实现去水印关键

一旦找到creations数据,脚本会遍历其中的每个图片项,并进行关键操作:

javascript 复制代码
const rawUrl = item.image.image_ori_raw.url;
item.image.image_ori.url = rawUrl;

这里,image_ori_raw.url代表无水印原图,而image_ori.url则是前端默认使用的水印版本。通过将后者指向前者,脚本实现了水印的去除。这种替换操作直接在数据层面完成,前端组件在不知情的情况下使用了无水印版本。

值得注意的是,脚本作者还细心地替换了预览图和缩略图的URL,确保在图片预览阶段也能看到无水印效果。这种细节处理提升了用户体验的一致性。

为脚本添加用户感知提示

一个技术优秀的工具如果缺乏用户反馈,会让人难以确认其是否正常工作。为此,需要为脚本添加清晰的状态提示机制。

提示方案设计考虑

在设计用户提示时,需要考虑几个关键因素:提示应明显但不过分干扰,需要确保只在脚本实际执行操作时显示,并且应当提供足够的上下文信息。基于这些考虑,可以采用以下几种提示方案。

浮动提示框方案:在页面角落显示一个临时性的浮动提示框,几秒后自动消失。这种方式视觉冲击力强,适合首次使用时的确认。

javascript 复制代码
function showFloatingToast() {
  const toast = document.createElement('div');
  toast.textContent = '豆包AI去水印脚本已激活,已成功拦截并替换水印URL';
  toast.style.cssText = 'position:fixed; top:20px; right:20px; background:#4CAF50; color:white; padding:12px; border-radius:4px; z-index:10000; box-shadow:0 4px 8px rgba(0,0,0,0.2);';
  document.body.appendChild(toast);
  
  setTimeout(() => {
    document.body.removeChild(toast);
  }, 3000);
}

状态栏消息方案:在页面顶部或底部添加一个不显眼的状态栏,显示脚本状态。这种方式干扰小,适合长期使用。

控制台日志方案:同时输出控制台日志,方便技术用户调试和验证。

提示触发逻辑优化

提示信息应当在脚本检测到creations数据并成功替换URL后显示。这意味着需要修改原有的JSON.parse函数,在完成替换操作后触发提示:

javascript 复制代码
JSON.parse = function(data) {
  let jsonData = _parse(data);
  if (!data.match('creations')) return jsonData;
  
  let creations = findAllKeysInJson(jsonData, 'creations');
  if (creations.length > 0) {
    // ...执行现有的URL替换逻辑...
    showFloatingToast(); // 添加提示
  }
  return jsonData;
};

集成用户提示的完整代码

将上述提示机制整合到原脚本中,得到以下完整实现:

javascript 复制代码
// ==UserScript==
// @name         豆包AI生图去水印(增强版)
// @namespace    http://tampermonkey.net/
// @version      1.2.0
// @description  豆包AI生图下载原图去水印,并添加用户提示
// @author       mzh
// @homepage https://blog.csdn.net/u011027547
// @match        https://www.doubao.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=doubao.com
// @grant        none
// @license      GPL-3.0
// @downloadURL https://update.greasyfork.org/scripts/558800/%E8%B1%86%E5%8C%85AI%E7%94%9F%E5%9B%BE%E5%8E%BB%E6%B0%B4%E5%8D%B0%EF%BC%88%E5%A2%9E%E5%BC%BA%E7%89%88%EF%BC%89.user.js
// @updateURL https://update.greasyfork.org/scripts/558800/%E8%B1%86%E5%8C%85AI%E7%94%9F%E5%9B%BE%E5%8E%BB%E6%B0%B4%E5%8D%B0%EF%BC%88%E5%A2%9E%E5%BC%BA%E7%89%88%EF%BC%89.meta.js
// ==/UserScript==

(function() {
    'use strict';

    let scriptActive = false;

    function showActivationMessage() {
        // 避免重复提示
        if (scriptActive) return;
        scriptActive = true;

        // 控制台日志
        console.log('🚫 豆包AI去水印脚本已激活,正在监控图片数据...');

        // 页面顶部状态栏
        const statusBar = document.createElement('div');
        statusBar.textContent = '豆包AI去水印:已启用(检测到图片生成时会自动去除水印)';
        statusBar.style.cssText = `
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            background: #4CAF50;
            color: white;
            padding: 8px;
            text-align: center;
            font-size: 14px;
            z-index: 9999;
            box-shadow: 0 2px 5px rgba(0,0,0,0.2);
        `;
        document.body.appendChild(statusBar);

        // 5秒后淡出状态栏
        setTimeout(() => {
            statusBar.style.transition = 'opacity 0.5s';
            statusBar.style.opacity = '0';
            setTimeout(() => {
                if (document.body.contains(statusBar)) {
                    document.body.removeChild(statusBar);
                }
            }, 500);
        }, 5000);
    }

    function showSuccessToast() {
        const toast = document.createElement('div');
        toast.innerHTML = '✅ 已成功去除图片水印,可下载无水印原图';
        toast.style.cssText = `
            position: fixed;
            top: 20px;
            right: 20px;
            background: #2196F3;
            color: white;
            padding: 12px 16px;
            border-radius: 4px;
            z-index: 10000;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            font-size: 14px;
            max-width: 300px;
        `;
        document.body.appendChild(toast);

        setTimeout(() => {
            if (document.body.contains(toast)) {
                toast.style.transition = 'opacity 0.5s';
                toast.style.opacity = '0';
                setTimeout(() => {
                    if (document.body.contains(toast)) {
                        document.body.removeChild(toast);
                    }
                }, 500);
            }
        }, 3000);
    }

    function findAllKeysInJson(obj, key) {
        const results = [];
        function search(current) {
            if (current && typeof current === 'object') {
                if (!Array.isArray(current) && Object.prototype.hasOwnProperty.call(current, key)) {
                    results.push(current[key]);
                }
                const items = Array.isArray(current) ? current : Object.values(current);
                for (const item of items) {
                    search(item);
                }
            }
        }
        search(obj);
        return results;
    }

    let _parse = JSON.parse;
    JSON.parse = function(data) {
        let jsonData = _parse(data);
        if (!data.match('creations')) return jsonData;

        let creations = findAllKeysInJson(jsonData, 'creations');
        if (creations.length > 0) {
            creations.forEach((creation) => {
                creation.map((item) => {
                    if (item.image && item.image.image_ori_raw && item.image.image_ori_raw.url) {
                        const rawUrl = item.image.image_ori_raw.url;
                        item.image.image_ori.url = rawUrl;
                        // 预览时也去水印
                        item.image.image_preview.url = rawUrl;
                        item.image.image_thumb.url = rawUrl;
                    }
                    return item;
                });
            });

            // 显示成功提示
            setTimeout(showSuccessToast, 500);
        }
        return jsonData;
    }

    // 页面加载后显示激活提示
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', showActivationMessage);
    } else {
        setTimeout(showActivationMessage, 1000);
    }
})();

豆包AI生图去水印(增强版)

🚀 一键自动去除豆包AI生成图片的水印,直接下载高清无水印原图!本脚本通过安全、非侵入式的技术方案,在后台静默处理图片数据,为您提供纯净的AI绘画体验。

功能亮点

• 自动去水印:监控豆包AI的生图过程,自动识别并替换带水印的图片为原始无水印版本。

• 全面覆盖:处理生成的原图(image_ori)、预览图(image_preview)及缩略图(image_thumb),确保您在查看和下载时均获得无水印图片。

• 用户友好提示:

复制代码
◦   脚本激活提示:页面加载后,顶部会显示绿色状态栏,提示脚本已启用。

◦   去水印成功提示:当检测到新图片生成并成功去除水印后,页面右下角会弹出蓝色提示框。

• 纯净安全:脚本仅操作图片数据,声明 @grant none 权限,不请求任何敏感API,不会将您的任何数据发送至第三方服务器。

• 低调静默:除必要的用户提示外,脚本在后台运行,不影响您正常使用豆包AI的其他功能。

使用方法

  1. 安装脚本:在脚本管理平台点击安装,Tampermonkey等油猴脚本管理器会自动识别并加载。
  2. 访问豆包AI:打开豆包AI的生图页面(例如 https://www.doubao.com/\*)。
  3. 正常生图:像往常一样输入提示词生成图片。
  4. 下载原图:图片生成后,脚本会自动处理水印。使用豆包AI原有的下载功能,即可保存无水印原图。

脚本运行后,您会看到如下提示:

• 页面加载时,顶部出现绿色状态栏,显示"豆包AI去水印:已启用..."。

• 每次成功生成图片后,右下角会弹出"✅ 已成功去除图片水印,可下载无水印原图"的提示。

技术原理

脚本通过重写 JSON.parse 方法,监控页面中的数据流。当检测到包含图片生成信息(如 creations 字段)的JSON数据时,会自动查找其中的原始图片URL(image_ori_raw.url),并用它替换掉带水印的图片URL。这个过程在数据层面完成,高效且无需修改页面布局。

常见问题

Q:脚本会影响豆包AI的其他功能吗?

A: 不会。脚本只针对图片数据URL进行替换,完全不影响文本对话、模型选择等所有其他功能。

Q:安装后为什么没有效果?

A: 请确保:

• 脚本已正确启用(Tampermonkey面板中该脚本开关为绿色)。

• 您访问的网址匹配 https://www.doubao.com/\*。

• 豆包AI的生图功能本身工作正常。如果问题依旧,请尝试刷新页面或检查浏览器控制台是否有错误信息。

Q:这个脚本安全吗?

A: 本脚本开源,代码透明。它仅运行在指定的豆包AI页面上,用于替换图片URL,不收集任何用户信息,也不申请高风险权限,非常安全。

Q:豆包AI更新后脚本失效怎么办?

A: 作者会尽力维护脚本的兼容性。如果遇到失效,请关注脚本的更新发布。您也可以通过脚本页面向作者反馈。

更新日志

• v1.1.0:增强提示体验,添加去水印成功Toast;优化代码逻辑,提升稳定性。

• v1.0.0:初始版本,实现基础的去水印功能。

开发者信息

• 作者:mzh

• 反馈与支持:如有问题或建议,请在脚本发布页面留言。

免责声明:本脚本仅为个人学习与交流方便而开发,旨在提升用户体验。请尊重豆包AI的服务条款,并仅将下载的图片用于合法用途。

许可证信息

本脚本采用GPL-3.0开源许可证发布。这意味着您可以自由使用、修改和分发本脚本,但修改后的版本必须同样以GPL-3.0许可证开源,并保留原始的版权声明和作者信息

总结与使用展望

这一经过优化的豆包AI生图去水印脚本,通过拦截并替换前端数据流中的图片URL,巧妙地实现了水印去除功能。新增的用户提示机制使脚本的工作状态清晰可见,大大提升了用户体验。

从技术角度看,这种基于JSON.parse钩子的方法不仅适用于豆包AI,对其他存在类似数据结构的平台也有参考价值。核心思路是在数据解析阶段进行干预,而非在渲染完成后修改,这通常更为高效和稳定。

需要注意的是,这类脚本的有效性依赖于目标网站的前端数据结构。如果豆包未来更改其API响应格式,脚本可能需要相应调整。但在可预见的未来,这一解决方案应该能持续为使用者提供便捷的无水印图片下载体验。

相关推荐
程序员差不多先生2 天前
仅仅三步完成豆包图像生成模型使用
豆包·模型api
dangdang___go2 天前
使用国产AI模型进行“委婉劝学程序”的模拟实现||创建可执行程序营造惊喜感
c语言·c++·豆包·劝学程序开发·创建可执行文件营造惊喜感
Navicat中国4 天前
Navicat 新增字节跳动豆包 AI
数据库·人工智能·sql·navicat·豆包
xcLeigh12 天前
AI 绘制图表专栏:用豆包轻松实现 HTML 柱状图、折线图与饼图
前端·人工智能·html·折线图·柱状图·图表·豆包
阿Q说代码21 天前
Trace+Doubao-Seed-Code快速构建休闲小游戏与精美门户网站
ai·豆包·ai编码·构建网站
码二哥22 天前
借助豆包将vllm推理deepseek-ocr改成web服务访问
ocr·fastapi·vllm·豆包·deepseek-ocr
涛涛讲AI23 天前
Gemini3对比豆包,不做游戏,不做图片拿我工作的实例对比
人工智能·扣子·豆包·gemini3
初九之潜龙勿用24 天前
C# 使用豆包 AI 模型实现首尾帧模式的视频生成
人工智能·microsoft·c#·ai编程·视频·ai模型·豆包
chao1898441 个月前
基于MATLAB的Arnold变换水印置乱实现
水印