231 lines
7.0 KiB
Markdown
231 lines
7.0 KiB
Markdown
# 分布式浏览器控制后台
|
||
|
||
通过 **中央服务器 + 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. 安装依赖
|
||
|
||
```bash
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 2. 启动中央服务器
|
||
|
||
在第三台机器(或任一台能被其他机器访问的机器)上运行:
|
||
|
||
```bash
|
||
python -m server.main
|
||
```
|
||
|
||
默认监听 `0.0.0.0:8000`。可通过环境变量修改:
|
||
|
||
```bash
|
||
set SERVER_HOST=0.0.0.0
|
||
set SERVER_PORT=8000
|
||
python -m server.main
|
||
```
|
||
|
||
### 3. 启动 Worker(每台电脑上各运行一个)
|
||
|
||
**电脑 A:**
|
||
```bash
|
||
python -m worker.main --server ws://服务器IP:8000/ws --worker-id pc-a --worker-name "电脑A"
|
||
```
|
||
|
||
**电脑 B:**
|
||
```bash
|
||
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
|
||
```
|
||
|
||
响应示例:
|
||
```json
|
||
[
|
||
{
|
||
"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.py` 的 `TaskType` 中添加新类型
|
||
4. 在 `worker/tasks/registry.py` 的 `register_all_handlers()` 中注册
|
||
|
||
```python
|
||
# 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 |
|