Browser Cluster 浏览器自动化集群爬虫系统

50 阅读7分钟

Browser Cluster 是一个高性能、分布式的浏览器自动化集群系统,基于 Playwright 和 FastAPI 构建。它支持大规模并发网页抓取、截图、PDF 生成及自动化操作,具备完善的任务调度、结果缓存和节点管理功能。

公众号python爬虫和阿J的逆向

项目地址github.com/934050259/B…

在这里插入图片描述

🚀 核心特性

  • 分布式架构:支持多 Worker 节点水平扩展,轻松应对高并发场景。
  • 隐身模式:内置 Stealth 插件,有效绕过反爬虫检测。
  • 高效缓存:基于 Redis 的结果缓存机制,支持自定义 TTL。
  • 资源优化:智能拦截图片、媒体资源,显著提升渲染速度。
  • API 拦截:支持在渲染过程中提取特定 XHR/Fetch 接口数据。
  • 可视化管理:提供基于 Vue 3 + Element Plus 的现代化管理后台。

🛠️ 技术栈

  • 后端:Python 3.10, FastAPI, Playwright, RabbitMQ, MongoDB, Redis
  • 前端:Vue 3, Element Plus, Pinia, Vite
  • 部署:Docker (Multi-stage build)

🏗️ 系统架构

在这里插入图片描述

🔄 任务处理流程

  1. 提交任务

    • 客户端向 API Gateway 发送抓取请求。
    • API 首先检查 Redis 缓存,若命中则直接返回结果。
  2. 任务调度

    • 若未命中缓存,API 在 MongoDB 创建任务记录(状态为 pending)。
    • 同时将任务消息发布到 RabbitMQ 队列。
    • API 立即返回 task_id 给客户端(异步模式)。
  3. 任务执行

    • 空闲的 Worker 节点从 RabbitMQ 消费任务。
    • Worker 启动浏览器上下文,执行页面加载、交互和数据提取。
  4. 结果回写

    • 成功:Worker 将结果写入 MongoDB,更新缓存到 Redis,并标记任务为 success。
    • 失败:记录错误信息到 MongoDB,标记任务为 failed。

核心组件

  • 🌐 API Gateway (FastAPI)

    • 系统的统一入口,负责接收 HTTP 请求、参数校验和任务调度。
    • 集成 Redis 缓存层,对重复请求直接返回缓存结果,显著降低系统负载。
    • 提供完整的任务管理、节点监控和系统配置 API。
  • 📨 Message Queue (RabbitMQ)

    • 异步任务总线,实现生产者(API)与消费者(Worker)的完全解耦。
    • 支持任务持久化、优先级队列和 ACK 确认机制,确保高并发下的任务可靠性。
  • 🤖 Worker Nodes (Playwright)

    • 分布式执行单元,支持容器化部署和水平扩展。
    • 负责启动浏览器上下文,执行页面渲染、交互、截图和数据提取。
    • 内置 Stealth Mode 和资源拦截策略,优化抓取成功率和速度。
  • 💾 Data Storage

    • MongoDB: 存储全量任务记录、抓取结果、节点状态和系统配置。
    • Redis: 用于热点数据缓存和分布式锁,提升系统响应速度。
  • 🖥️ Admin Dashboard (Vue 3)

    • 统计监控:实时展示任务成功率、处理时长及队列堆积情况。
    • 任务管理:全量任务历史溯源,支持结果预览及错误日志查看。
    • 节点管理:监控集群 Worker 状态、负载情况及资源占用。
    • 配置管理:动态调整浏览器并发数、超时时间及全局代理设置。
    • 用户管理:基于角色的访问控制 (RBAC),保障系统安全。

📦 快速开始

前置要求

  • Python 3.10
  • Node.js 22
  • RabbitMQ, MongoDB, Redis

本地开发

  1. 克隆仓库

    git clone https://github.com/934050259/BrowserCluster.git
    cd browser-cluster
    
  2. 环境配置 复制示例配置文件并根据实际环境修改:

    cp .env.example .env
    # Windows (PowerShell)
    # copy .env.example .env
    

    修改 .env 文件中的数据库和消息队列连接信息:

    MONGO_URI=mongodb://localhost:27017/
    REDIS_URL=redis://localhost:6379/0
    RABBITMQ_URL=amqp://guest:guest@localhost:5672/
    
  3. 初始化配置与账号 运行初始化脚本,导入默认配置并创建初始管理员账号:

    # 初始化系统配置
    python scripts/init_configs_db.py
    
    # 初始化默认管理员账号 (账号: admin, 密码: admin)
    python scripts/init_admin.py
    
  4. 后端设置

    # 安装依赖
    pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
    playwright install chromium
    
    # 启动 API 服务
    uvicorn app.main:app --reload
    
  5. 前端设置

    cd admin
    npm install
    npm run build  # 构建后由后端统一托管,或运行 npm run dev 进行开发
    
  6. 访问系统

    • 管理后台:http://localhost:8000 (后端托管) 或 http://localhost:5173 (Vite 开发模式)
    • API 文档:http://localhost:8000/docs

🐳 Docker 部署

本项目支持多阶段构建,镜像内已集成前端静态资源和后端服务。

1. 配置镜像加速 (可选)

为了提升国内构建速度,建议配置 Docker 镜像加速器。

2. 构建镜像

docker build -t browser-cluster:latest .

3. 运行容器

推荐使用 --env-file 传递本地配置:

docker run -d `
  --name browser-cluster `
  -p 8000:8000 `
  --env-file .env `
  -v ${PWD}/logs:/app/logs `
  browser-cluster:latest

注意

  1. 请确保 .env 中的 MONGO_URIREDIS_URL 等地址对容器可见(如使用宿主机 IP)。
  2. ${PWD}/logs 用于持久化日志。

⚙️ 配置说明

主要配置项(可通过 .env 或环境变量设置):

变量名默认值说明
MONGO_URImongodb://localhost:27017/MongoDB 连接地址
REDIS_URLredis://localhost:6379/0Redis 队列/缓存连接地址
RABBITMQ_URLamqp://guest:guest@localhost:5672/RabbitMQ 连接地址
BROWSER_TYPEchromium浏览器类型
HEADLESStrue是否开启无头模式
WORKER_CONCURRENCY3单个 Worker 的并发线程数
NODE_IDnode-1节点唯一标识

📝 任务参数说明

1. 抓取接口 (POST /api/v1/scrape)

这是最核心的接口,支持同步抓取并返回渲染后的结果。

请求体 (JSON)

参数名类型必选默认值说明
urlstring-目标网页的完整 URL 地址
paramsobject{}详细的抓取配置参数(见下表)
cacheobject{"enabled": true, "ttl": 3600}缓存配置(见下表)
priorityint1任务优先级,数字越大越优先处理

cache 配置详解

参数名类型默认值说明
enabledbooltrue是否启用缓存
ttlint3600缓存过期时间(秒),默认 1 小时

params 配置详解

参数名类型默认值说明
wait_forstringnetworkidle等待策略:networkidle (网络空闲), load (加载完成), domcontentloaded
wait_timeint3000页面加载完成后的额外等待时间(毫秒),用于处理异步渲染
timeoutint30000抓取总超时时间(毫秒)
selectorstringnull等待特定的 CSS 选择器出现后再返回结果
screenshotboolfalse是否生成页面截图
is_fullscreenboolfalse是否截取全屏(仅在 screenshot 为 true 时生效)
block_imagesboolfalse是否拦截图片资源加载,可显著提升速度
block_mediaboolfalse是否拦截视频、音频、字体、CSS 等媒体和资源
user_agentstringnull自定义浏览器 User-Agent
stealthbooltrue是否启用反检测插件,模拟真实人类行为
intercept_apislist[]要拦截并提取数据的接口 URL 模式列表(支持正则)
intercept_continueboolfalse拦截接口后是否继续请求(默认 False 为中止请求)
viewportobject{"width": 1920, "height": 1080}模拟的浏览器视口大小
proxyobjectnull代理服务器配置,格式:{"server": "...", "username": "...", "password": "..."}
cookiesstring/object/listnull注入 Cookie。支持字符串 (name=val;), JSON 对象 ({name: val}) 或 JSON 数组 ([{name, value, ...}])。自动适配主域名。

请求示例

{
  "url": "https://example.com",
  "params": {
    "wait_for": "networkidle",
    "screenshot": true,
    "block_images": true,
    "stealth": true,
    "cookies": "name=value; session=123",
    "intercept_apis": ["/api/v1/data/.*"],
    "proxy": {
      "server": "http://proxy.example.com:8080"
    }
  },
  "cache": {
    "enabled": true,
    "ttl": 3600
  }
}

2. 异步抓取 (POST /api/v1/scrape/async)

异步提交抓取任务,不等待执行结果,立即返回任务 ID。适用于耗时较长的任务或不需要即时响应的场景。

请求体

与同步抓取接口 (/api/v1/scrape) 完全一致。

响应示例

{
  "task_id": "65b2...",
  "url": "https://example.com",
  "status": "pending",
  "created_at": "2024-01-25T10:00:00"
}

3. 批量抓取 (POST /api/v1/scrape/batch)

支持一次性提交多个抓取任务。批量接口目前仅支持异步模式,不直接返回抓取结果。

请求体

{
  "tasks": [
    {
      "url": "https://example.com/1",
      "params": { ... }
    },
    {
      "url": "https://example.com/2",
      "priority": 2
    }
  ]
}

4. 任务管理接口

用于查询异步/批量任务的执行状态和结果。

接口方法说明
/api/v1/tasks/{task_id}GET获取单个任务详情(包含抓取结果)
/api/v1/tasksGET分页获取任务列表,支持状态/URL搜索
/api/v1/tasks/{task_id}/retryPOST重试失败的任务
/api/v1/tasks/{task_id}DELETE删除指定任务
/api/v1/tasks/batchDELETE批量删除任务