构建一个基于 Python 的在线 Web 截图服务,提供一个Web 前端管理 Docker 中的 Chrome(使用镜像 selenium/standalone-chrome:latest)并能实时预览容器内 Chrome 页面的能力。目标用户为需要远程批量抓取页面截图、生成缩略图以及人工审核/预览页面渲染效果的产品/测试人员。
POST /api/screenshot:提交截图任务(参数:url, width, height, full_page, wait_selector/wait_ms, device_pixel_ratio, cookies/headers 等)。GET /api/screenshot/{id}:获取任务状态与结果(或重定向到图片)。GET /api/containers:列出管理的容器。POST /api/containers/{id}/start/stop:控制容器。[用户浏览器] <--HTTPS--> [前端 (React/Vue)] | v [后端 API (FastAPI/Flask)] | +------------+-------------+ | | [任务队列:Redis/RQ 或 Celery + Redis/RabbitMQ] | | [Worker] [Docker 管理器] | (docker-py) v | 启动/连接 selenium 容器 <-----> docker host (运行 selenium/standalone-chrome) | | 通过 Selenium / CDP 控制 Chrome noVNC (可选) 提供实时 VNC 预览
selenium/standalone-chrome:latest(自带 VNC,可通过 noVNC 访问)。使用 docker-py(Python SDK)启动 selenium 镜像:示例参数包括端口映射、环境变量(如 VNC 密码)、资源限制(cgroups)。每个用户/任务可以绑定一个短寿命容器或复用池中的容器。
两条主路径:
fullPage:使用 Chrome DevTools 的 Page.captureScreenshot + 滚动或 CDP 的 Emulation.setDeviceMetricsOverride。wait_selector)、固定延时、或页面网络空闲(可检测网络请求数)。POST /api/screenshot Content-Type: application/json { "url":"https://example.com", "width":1280, "height":800, "full_page":true, "wait_for_selector":"#ready", "timeout_ms":20000 } 200 OK { "task_id":"uuid-1234", "status":"queued" }
GET /api/screenshot/{task_id} 200 OK { "task_id":"...", "status":"done", "image_url":"/files/..../uuid.png", "meta":{...} }
version: '3'
services:
chrome:
image: selenium/standalone-chrome:latest
shm_size: '2g'
ports:
- "4444:4444" # selenium
- "5900:5900" # vnc(如有)
- "7900:7900" # noVNC(镜像支持时)
environment:
- SE_VNC_PASSWORD=secret
volumes:
- ./screens:/screens
web-screenshot-app/ ├─ backend/ │ ├─ Dockerfile │ ├─ requirements.txt │ ├─ app/ │ │ ├─ main.py │ │ ├─ api.py │ │ ├─ tasks.py │ │ ├─ docker_manager.py │ │ └─ utils.py │ └─ start.sh ├─ frontend/ │ ├─ Dockerfile │ ├─ package.json │ ├─ vite.config.js │ └─ src/ │ ├─ main.jsx │ ├─ App.jsx │ ├─ api.js │ └─ index.css └─ docker-compose.yml