# DouBao2Api 将网页版豆包(doubao.com)转换为 OpenAI 兼容 API 的 Docker 化方案。通过 VNC + Playwright 模拟真人浏览器操作,间接发送消息并捕获回复,对外暴露标准 `/v1/chat/completions` 接口。

[**中文**](README.md) | [English](README_EN.md)
## 工作原理 ``` ┌──────────────────────────────────────────────────────────┐ │ Docker 容器 (RockyLinux 9) │ │ │ │ ┌─────────┐ ┌──────────┐ ┌──────────┐ ┌────────┐ │ │ │ Xvfb │──│ openbox │──│ Chromium │──│Playwright│ │ │ │ 虚拟显示 │ │ 窗口管理器 │ │ 浏览器 │ │ 自动化 │ │ │ └─────────┘ └──────────┘ └──────────┘ └────────┘ │ │ │ │ │ │ │ ┌──────────┐ │ │ │ └──────────│ x11vnc │◄───────────────────┘ │ │ │ VNC 服务 │ │ │ └────┬─────┘ │ │ │ │ │ ┌────┴─────┐ ┌──────────┐ │ │ │websockify│──│ noVNC │ │ │ │ 代理 │ │ Web 客户端 │ │ │ └──────────┘ └──────────┘ │ │ │ │ ┌──────────────────────┐ │ │ │ FastAPI (端口 8000) │ │ │ │ OpenAI 兼容 API │ │ │ └──────────────────────┘ │ └──────────────────────────────────────────────────────────┘ │ │ │ ▼ ▼ ▼ API :8000 VNC :5900 noVNC :6080 ``` **核心流程**:API 收到请求 → Playwright 在 Chromium 中操作豆包页面(输入消息、Enter 发送) → DOM 轮询捕获流式回复 → 以 SSE 或 JSON 返回。 ## 功能特性 - **OpenAI 兼容**:标准 `/v1/chat/completions` 接口,支持流式(SSE)和非流式响应 - **VNC 可视化**:通过 noVNC Web 客户端实时查看浏览器画面,支持只读/交互切换 - **反检测**:Playwright stealth 脚本隐藏 webdriver 标志,模拟人类打字延迟 - **会话持久化**:登录状态通过 `storage_state` 保存到 Docker volume,重启免登录 - **聊天复用**:默认复用当前聊天会话,降低风控风险;支持按需新建对话 - **调试端点**:`/inspect` 返回页面 DOM 结构,方便选择器适配 ## 快速开始 ### 1. 构建与启动 ```bash docker compose build docker compose up -d ``` ### 2. 登录豆包 容器启动后,浏览器打开 noVNC: ``` http://localhost:6080/vnc.html ``` VNC 密码:`doubao123`(可在 `docker-compose.yml` 中修改 `VNC_PASSWORD`) noVNC 默认为**只读模式**(防止误触)。在左侧设置面板取消勾选 "View Only" 即可切换到交互模式。 在 VNC 中的 Chromium 浏览器里登录豆包账号,确认能看到聊天输入框。 ### 3. 保存登录状态 ```bash curl -X POST http://localhost:8000/login/save ``` ### 4. 调用 API ```bash # 非流式 curl http://localhost:8000/v1/chat/completions \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"model":"doubao-pro","messages":[{"role":"user","content":"你好"}]}' # 流式 curl http://localhost:8000/v1/chat/completions \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"model":"doubao-pro","messages":[{"role":"user","content":"你好"}],"stream":true}' ``` ## 配置项 所有配置通过环境变量设置,在 `docker-compose.yml` 或 `.env` 中修改: | 环境变量 | 默认值 | 说明 | |---------|--------|------| | `API_KEY` | `sk-your-api-key-here` | API 鉴权密钥,客户端需在 Header 中携带 `Authorization: Bearer ` | | `API_PORT` | `8000` | API 服务端口 | | `VNC_PASSWORD` | `doubao123` | VNC 连接密码 | | `VNC_VIEW_ONLY` | `false` | x11vnc 服务端是否强制只读(`true` 时即使 noVNC 取消勾选也无法操作) | | `VNC_PORT` | `5900` | VNC 直连端口 | | `NOVNC_PORT` | `6080` | noVNC Web 客户端端口 | | `DOUBAO_URL` | `https://www.doubao.com/chat/` | 豆包聊天页面 URL | | `BROWSER_HEADLESS` | `false` | 浏览器是否无头模式(VNC 方案需设为 `false`) | | `RESPONSE_TIMEOUT` | `120` | 响应超时时间(秒) | | `TYPING_DELAY_MIN` | `30` | 打字延迟下限(毫秒/字符) | | `TYPING_DELAY_MAX` | `80` | 打字延迟上限(毫秒/字符) | | `INTER_MESSAGE_DELAY` | `0.5` | 消息发送前等待时间(秒) | | `SCREEN_WIDTH` | `1280` | 虚拟屏幕宽度 | | `SCREEN_HEIGHT` | `720` | 虚拟屏幕高度 | | `SCREEN_DEPTH` | `24` | 虚拟屏幕色深 | | `LOG_LEVEL` | `INFO` | 日志级别 | ## API 接口 ### `POST /v1/chat/completions` OpenAI 兼容的对话接口。 | 参数 | 类型 | 默认值 | 说明 | |------|------|--------|------| | `model` | string | `doubao-pro` | 模型名称 | | `messages` | array | 必填 | 消息数组,同 OpenAI 格式 | | `stream` | bool | `false` | 是否流式返回 | | `new_chat` | bool | `false` | 是否新建聊天会话(自定义扩展字段) | ### `GET /v1/models` 返回支持的模型列表。 ### `GET /login/status` 检查当前豆包登录状态。 ### `POST /login/save` 保存当前浏览器状态(cookies、storage)到磁盘。 ### `POST /chat/new` 显式开启新的豆包聊天会话。 ### `GET /inspect` 返回当前页面的 DOM 结构信息,用于调试选择器。 ### `GET /vnc/mode` 查看当前 VNC 模式(`viewonly` 或 `interactive`)。 ### `POST /vnc/mode` 切换 VNC 模式(服务端强制): ```bash # 切换到交互模式 curl -X POST http://localhost:8000/vnc/mode \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"mode":"interactive"}' # 切换到只读模式 curl -X POST http://localhost:8000/vnc/mode \ -H "Authorization: Bearer sk-your-api-key-here" \ -H "Content-Type: application/json" \ -d '{"mode":"viewonly"}' ``` ### `POST /browser/restart` 重启浏览器会话。 ### `GET /health` 健康检查端点。 ## VNC 模式说明 提供两层只读控制: | 层级 | 控制方式 | 默认 | 说明 | |------|---------|------|------| | 客户端 | noVNC 侧边栏 "View Only" 勾选框 | 勾选(只读) | 取消勾选即时切换到交互模式,刷新后恢复只读 | | 服务端 | API `POST /vnc/mode` | `interactive` | `viewonly` 模式下 x11vnc 拒绝所有输入,即使客户端取消勾选也无效 | 日常使用:客户端层即可满足需求。如需更强控制(防止任何 VNC 客户端操作),使用 API 切换服务端模式。 ## 项目结构 ``` DouBao2Api/ ├── Dockerfile # Docker 镜像构建文件 ├── docker-compose.yml # 容器编排配置 ├── requirements.txt # Python 依赖 ├── .env.example # 环境变量模板 ├── app/ │ ├── __init__.py │ ├── config.py # 配置管理(pydantic-settings) │ ├── models.py # OpenAI 兼容数据模型 │ ├── browser_manager.py # Playwright 浏览器管理 │ ├── doubao.py # 豆包页面交互逻辑 │ └── main.py # FastAPI 服务入口 └── scripts/ ├── entrypoint.sh # 容器入口脚本 ├── supervisord.conf # 进程管理配置 ├── start_wm.sh # 窗口管理器启动脚本 └── start_x11vnc.sh # x11vnc 启动脚本(支持只读/交互切换) ``` ## 进程架构 容器内通过 supervisord 管理五个进程,按优先级启动: | 优先级 | 进程 | 说明 | |--------|------|------| | 10 | Xvfb | 虚拟帧缓冲 X 服务器 | | 20 | openbox | 轻量级窗口管理器 | | 30 | x11vnc | VNC 服务器,映射 Xvfb 显示 | | 40 | websockify | WebSocket 代理,提供 noVNC Web 访问 | | 50 | uvicorn | FastAPI 应用服务器 | ## 常见问题 ### 构建失败:找不到包 本项目基于 RockyLinux 9。RHEL 10 / RockyLinux 10 移除了 X11 server 包,不支持本方案。Docker 容器独立于宿主系统,在 RL10 宿主上运行 RL9 容器完全兼容。 ### API 返回空响应 豆包前端更新可能导致 CSS 选择器失效。调用 `GET /inspect` 查看当前 DOM 结构,然后修改 `app/doubao.py` 中的选择器常量。 ### 提示 "Not logged in" 需先通过 VNC 浏览器登录豆包,再调用 `POST /login/save` 保存状态。调用 `GET /login/status` 检查登录状态。 ### VNC 无法操作 确认 noVNC 侧边栏 "View Only" 已取消勾选。若仍无法操作,检查服务端模式:`GET /vnc/mode`,如为 `viewonly` 则调用 API 切换为 `interactive`。 ## 技术栈 - **RockyLinux 9** — 容器基础系统 - **Xvfb + x11vnc + noVNC** — 虚拟显示与远程查看 - **Playwright** — 浏览器自动化 - **FastAPI + Uvicorn** — API 服务 - **Supervisor** — 进程管理 - **websockify** — VNC over WebSocket 代理 ## 免责声明 本项目仅供学习和研究用途。使用前请确保遵守豆包的服务条款。作者不对因使用本项目而产生的任何直接或间接后果承担责任。