Files
boss_dp/README.md
ddrwode 4a520306b1 ha'ha
2026-02-12 16:46:01 +08:00

7.0 KiB
Raw Blame History

分布式浏览器控制后台

通过 中央服务器 + Worker 代理 架构,远程控制多台电脑上的比特浏览器,并使用 DrissionPage 执行自动化任务。


架构概览

前端 / Postman                 中央服务器(第三台机器)              电脑 A / B
───────────────               ─────────────────────              ──────────
   REST API  ──── HTTP ────→  FastAPI Server                    Worker Agent
                                ├── Worker Manager  ←── WebSocket ──┤
                                └── Task Dispatcher ──── WebSocket ──→ 比特浏览器
                                                                       + DrissionPage
  • 中央服务器:接收前端 API 请求,管理 Worker 状态,路由并派发任务
  • Worker 代理:运行在每台电脑上,通过 WebSocket 连接服务器,接收任务后本地控制比特浏览器 + DrissionPage

快速开始

1. 安装依赖

pip install -r requirements.txt

2. 启动中央服务器

在第三台机器(或任一台能被其他机器访问的机器)上运行:

python -m server.main

默认监听 0.0.0.0:8000。可通过环境变量修改:

set SERVER_HOST=0.0.0.0
set SERVER_PORT=8000
python -m server.main

3. 启动 Worker每台电脑上各运行一个

电脑 A

python -m worker.main --server ws://服务器IP:8000/ws --worker-id pc-a --worker-name "电脑A"

电脑 B

python -m worker.main --server ws://服务器IP:8000/ws --worker-id pc-b --worker-name "电脑B"

Worker 启动后会自动:

  1. 连接中央服务器
  2. 上报本机比特浏览器窗口列表
  3. 等待接收任务

注意:每台电脑需先启动比特浏览器客户端(默认 API 端口 54345


内网穿透(隧道)

项目内置 独立 Python 隧道,与 Worker 集成。线下电脑无需单独安装 frp 等工具,启动 Worker 时会同时建立隧道,将本机端口(如比特浏览器 API 54345暴露到云服务器便于从公网访问该机器上的服务。

  • 云服务器:随 python -m server.main 自动启动隧道服务端(控制端口 8001、流端口 8003、代理端口从 8010 起按 Worker 分配)。
  • 线下电脑Worker 启动时默认开启隧道客户端,连接云服务器并注册 worker_id,云上会为该 Worker 分配一个代理端口(如 8010、8011…。访问 云服务器IP:8010 即等价于访问该 Worker 本机的 127.0.0.1:54345

环境变量(可选)

位置 变量 默认值 说明
服务器 TUNNEL_CONTROL_PORT 8001 隧道控制端口
服务器 TUNNEL_STREAM_PORT 8003 隧道流端口
服务器 TUNNEL_PROXY_BASE_PORT 8010 代理端口起始
Worker TUNNEL_ENABLED 1 是否启用隧道
Worker TUNNEL_SERVER (从 SERVER_WS_URL 解析) 隧道服务端地址
Worker TUNNEL_LOCAL_PORT 54345 暴露的本地端口

禁用隧道python -m worker.main --no-tunnel ...


API 接口

查看在线 Worker

GET /api/workers

响应示例:

[
  {
    "worker_id": "pc-a",
    "worker_name": "电脑A",
    "browsers": [
      {"id": "abc123", "name": "BOSS主号", "remark": "张三"}
    ],
    "online": true,
    "current_task_id": null
  }
]

提交任务

POST /api/tasks
Content-Type: application/json

{
  "task_type": "boss_recruit",
  "account_name": "BOSS主号",
  "params": {
    "job_title": "前端工程师",
    "max_greet": 5
  }
}

路由规则:

  • 指定 worker_id → 直接发到该 Worker
  • 指定 account_name → 自动找到拥有该浏览器的 Worker
  • 两者都传 → worker_id 优先

查询任务状态

GET /api/tasks/{task_id}

查询任务列表

GET /api/tasks?worker_id=pc-a&status=success&limit=20

健康检查

GET /health

项目结构

boss_dp/
├── server/                        # 中央服务器
│   ├── main.py                    # FastAPI 入口(含 WebSocket 端点)
│   ├── config.py                  # 服务器配置
│   ├── models.py                  # Pydantic 数据模型
│   ├── api/
│   │   ├── workers.py             # Worker 查询 API
│   │   └── tasks.py               # 任务提交与查询 API
│   └── core/
│       ├── worker_manager.py      # Worker 注册、状态管理、账号映射
│       └── task_dispatcher.py     # 任务路由与派发
├── worker/                        # Worker 代理(每台电脑部署)
│   ├── main.py                    # 启动入口
│   ├── config.py                  # Worker 配置
│   ├── ws_client.py               # WebSocket 客户端(心跳、重连)
│   ├── bit_browser.py             # 比特浏览器 API 封装
│   ├── browser_control.py         # DrissionPage 通用控制封装
│   └── tasks/
│       ├── base.py                # 任务处理器基类
│       ├── registry.py            # 处理器注册表
│       └── boss_recruit.py        # BOSS 直聘招聘任务
├── common/
│   └── protocol.py                # 共享消息协议
├── tunnel/                        # 内网穿透(独立隧道,与 Worker 集成)
│   ├── __init__.py
│   ├── protocol.py                # 隧道控制协议
│   ├── server.py                  # 隧道服务端(云上)
│   └── client.py                  # 隧道客户端(线下,随 Worker 启动)
├── requirements.txt
└── README.md

扩展新任务

  1. worker/tasks/ 下新建文件,继承 BaseTaskHandler
  2. 实现 execute 方法
  3. common/protocol.pyTaskType 中添加新类型
  4. worker/tasks/registry.pyregister_all_handlers() 中注册
# worker/tasks/my_task.py
from worker.tasks.base import BaseTaskHandler

class MyTaskHandler(BaseTaskHandler):
    task_type = "my_task"

    async def execute(self, task_id, params, progress_cb):
        await progress_cb(task_id, "开始执行...")
        # ... 你的自动化逻辑 ...
        return {"status": "done"}

配置项

服务器 (server/config.py)

环境变量 默认值 说明
SERVER_HOST 0.0.0.0 监听地址
SERVER_PORT 8000 监听端口
API_TOKEN (空) 非空时校验 Authorization Header

Worker (worker/config.py)

环境变量 默认值 说明
SERVER_WS_URL ws://127.0.0.1:8000/ws 服务器 WebSocket 地址
WORKER_ID worker-1 Worker 唯一标识
WORKER_NAME 本机 Worker 显示名称
BIT_API_BASE http://127.0.0.1:54345 比特浏览器本地 API