a high performance distributed task scheduler and retry management center
Project description
🎭 基于 SnailJob 的通用 Playwright 自动化任务执行器
Playwright Executor
基于 SnailJob 的通用 Playwright 自动化任务执行器,专为执行存储在 GitLab 中的 Playwright 项目而设计。
核心特性
- ✅ 自动代码拉取: 从 GitLab 自动克隆/更新代码仓库
- ✅ 环境隔离: 每个业务独立的虚拟环境,避免依赖冲突
- ✅ 智能依赖管理: 基于 MD5 校验,仅在依赖变化时重新安装
- ✅ 实时日志: 执行日志实时上报到 SnailJob 服务器
- ✅ 任务控制: 支持任务中断和超时控制
- ✅ Docker 部署: 生产环境就绪,支持 Docker Compose 一键部署
工作原理
SnailJob 调度任务
↓
Playwright Executor 接收任务
↓
Git Manager: 拉取代码 (clone/pull)
↓
Env Manager: 按业务逻辑文件夹创建独立虚拟环境 + 安装依赖 (MD5校验)
↓
Script Runner: 动态导入 main.py
↓
调用 run(extra_params) 方法
↓
监控执行 (超时/中断检测)
↓
返回结果到 SnailJob
快速开始
前置条件
- Python 3.10+
- GitLab 仓库访问权限
- SnailJob 服务器
方式一:Docker Compose 部署(推荐)
# 1. 配置环境变量
cp env.example .env
# 编辑 .env,填入 GIT_TOKEN 和 SNAIL_SERVER_HOST
# 2. 部署执行器
./deploy.sh docker-compose
# 3. 查看日志
docker-compose logs -f
方式二:本地开发部署
# 1. 克隆项目
git clone https://gitee.com/opensnail/snail-job-python.git
cd snail-job-python
# 2. 配置环境变量
cp env.example .env
# 编辑 .env 文件
# 3. 安装依赖
pip install -r requirements.txt
# 4. 启动执行器
python main.py
方式三:使用部署脚本
# 本地部署
./deploy.sh local
# Docker 部署
./deploy.sh docker
# Docker Compose 部署
./deploy.sh docker-compose
环境配置
环境变量说明
必需配置
| 环境变量 | 说明 | 示例 | 备注 |
|---|---|---|---|
GIT_REPO_URL |
Git 仓库地址 | https://gitlab.com/org/project.git或 git@github.com:org/project.git |
支持 HTTPS 和 SSH 两种格式 |
GIT_TOKEN |
Git 访问令牌 | glpat-xxxxxxxxxxxx |
仅 HTTPS 方式需要,SSH 方式不需要 |
SNAIL_SERVER_HOST |
SnailJob 服务器地址 | 192.168.1.100 |
- |
SNAIL_SERVER_PORT |
SnailJob 服务器端口 | 1788 |
- |
可选配置
| 环境变量 | 说明 | 默认值 |
|---|---|---|
SNAIL_NAMESPACE |
命名空间 | default |
SNAIL_GROUP_NAME |
组名 | playwright_group |
SNAIL_APP_NAME |
应用名 | playwright_executor |
SNAIL_HOST_IP |
客户端 IP | 自动获取 |
SNAIL_HOST_PORT |
客户端端口 | 1633 |
LOG_ENV |
日志环境 | remote |
配置示例
创建 .env 文件:
# Git 配置(必需)
GIT_REPO_URL=https://gitlab.com/your-org/playwright-project.git
GIT_TOKEN=glpat-xxxxxxxxxxxx
# SnailJob 服务端配置(必需)
SNAIL_SERVER_HOST=192.168.1.100
SNAIL_SERVER_PORT=1788
# SnailJob 客户端配置(可选)
SNAIL_NAMESPACE=default
SNAIL_GROUP_NAME=playwright_group
Git 仓库访问方式
执行器支持两种方式访问 Git 仓库:SSH(推荐)和 HTTPS。
方式一:SSH 方式(推荐)⭐
优势:
- ✅ 不受 GitHub/GitLab 限流影响
- ✅ 连接更稳定,性能更好
- ✅ 无需在 URL 中嵌入 token,更安全
- ✅ 支持 GitHub 和 GitLab(包括自建 GitLab)
配置步骤:
-
生成 SSH key(如果还没有):
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
-
将公钥添加到 GitHub/GitLab:
# 复制公钥内容 cat ~/.ssh/id_rsa.pub
- GitHub: Settings → SSH and GPG keys → New SSH key
- GitLab: Settings → SSH Keys → Add SSH Key
-
修改
.env文件,使用 SSH URL:# GitHub SSH URL GIT_REPO_URL=git@github.com:laizezhong/rpa-projects.git # 或 GitLab SSH URL # GIT_REPO_URL=git@gitlab.com:zezhong.lai/rpa-projects.git # 或自建 GitLab SSH URL # GIT_REPO_URL=git@gitlab.yeepay.com:zezhong.lai/rpa-projects.git # 注意:使用 SSH 时不需要 GIT_TOKEN
-
确保 SSH key 文件存在:
# 检查文件是否存在 ls -la ~/.ssh/id_rsa # 如果不存在,请先生成 SSH key
-
重启容器:
docker-compose down docker-compose up -d
注意事项:
- 确保宿主机
~/.ssh/id_rsa文件存在且已添加到 GitHub/GitLab - Docker Compose 会自动挂载
~/.ssh/id_rsa到容器中 - 对于自建 GitLab,如果首次连接,可能需要手动添加 known_hosts
方式二:HTTPS 方式
适用场景:
- 临时使用或测试环境
- 无法配置 SSH key 的环境
配置步骤:
-
获取 Git Token:
- GitHub: Settings → Developer settings → Personal access tokens → Generate new token
- GitLab: Settings → Access Tokens → Create personal access token
-
修改
.env文件:# GitHub HTTPS URL GIT_REPO_URL=https://github.com/laizezhong/rpa-projects.git GIT_TOKEN=github_pat_XXXX # 或 GitLab HTTPS URL # GIT_REPO_URL=https://gitlab.yeepay.com/zezhong.lai/rpa-projects.git # GIT_TOKEN=glpat-XXXX
注意事项:
- ⚠️ HTTPS 方式可能遇到限流问题(特别是频繁 clone/pull 时)
- 如果遇到
GnuTLS recv error (-110)等错误,建议切换到 SSH 方式
业务开发指南
GitLab 项目结构
RPA项目的 GitLab 仓库需要按照以下结构组织:
your-playwright-project/
├── requirements.txt # 根目录通用依赖(可选)
└── app/
└── services/ # RPA业务逻辑父目录(固定路径)
├── demo_service/ # 业务子文件夹(配置时只需写 demo_service)
│ ├── main.py # 必需:包含 run() 方法
│ ├── requirements.txt # 可选:业务特定依赖
│ └── config.json # 可选:业务配置
└── other_service/ # 配置时只需写 other_service
└── main.py
编写业务脚本
1. 固定的 run() 方法签名(必需)
每个业务的 main.py 必须实现以下方法:
import snailjob as sj
def run(extra_params: dict = None) -> int:
"""
执行器的入口方法(必需)
Args:
extra_params: 从 SnailJob 任务参数传递的额外参数字典
Returns:
int: 返回码
- 0: 执行成功
- 非0: 执行失败
"""
try:
# 1. 从 extra_params 获取参数
target_url = extra_params.get("target_url", "https://example.com") if extra_params else "https://example.com"
# 2. 使用 sj.SnailLog.AUTO 记录日志(自动适配本地/远程)
sj.SnailLog.AUTO.info(f"开始执行任务,目标URL: {target_url}")
# 3. 执行业务逻辑
result = your_business_logic(target_url)
# 4. 记录成功日志
sj.SnailLog.AUTO.info(f"任务执行成功: {result}")
return 0
except Exception as e:
# 5. 记录错误日志
sj.SnailLog.AUTO.error(f"任务执行失败: {str(e)}")
import traceback
sj.SnailLog.AUTO.error(traceback.format_exc())
return 1
2. 使用 Playwright
import snailjob as sj
from playwright.sync_api import sync_playwright
def run(extra_params: dict = None) -> int:
try:
target_url = extra_params.get("target_url", "https://example.com") if extra_params else "https://example.com"
sj.SnailLog.AUTO.info(f"开始访问: {target_url}")
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto(target_url)
title = page.title()
sj.SnailLog.AUTO.info(f"页面标题: {title}")
browser.close()
sj.SnailLog.AUTO.info("执行完成")
return 0
except Exception as e:
sj.SnailLog.AUTO.error(f"执行失败: {str(e)}")
import traceback
sj.SnailLog.AUTO.error(traceback.format_exc())
return 1
3. 导入通用工具类
# 直接导入即可,执行器会自动添加项目根目录到 sys.path
from common.utils import some_util_function
from common.db_client import DatabaseClient
def run(extra_params: dict = None) -> int:
result = some_util_function()
db = DatabaseClient()
# ...
return 0
4. 本地调试
if __name__ == "__main__":
# 本地测试
test_params = {
"target_url": "https://example.com"
}
exit_code = run(extra_params=test_params)
print(f"执行结果: {exit_code}")
日志使用
使用 SnailLog.AUTO(推荐)⭐
推荐使用 sj.SnailLog.AUTO,自动适配本地测试和远程执行!
import snailjob as sj
def run(extra_params: dict = None) -> int:
# 使用 AUTO 日志,无需关心运行环境
sj.SnailLog.AUTO.info("开始执行")
sj.SnailLog.AUTO.warning("警告信息")
sj.SnailLog.AUTO.error("错误信息")
return 0
工作原理:
- 本地测试(直接运行
python main.py):自动使用本地日志 - 远程执行(SnailJob 调度):自动上报到 SnailJob 服务器
手动指定日志类型(可选)
# 仅本地日志(不上报)
sj.SnailLog.LOCAL.info("本地日志")
# 远程日志(会上报到 SnailJob)
sj.SnailLog.REMOTE.info("远程日志")
依赖管理
snailjob 包(自动安装)
重要: snailjob 包会自动安装到每个业务的虚拟环境中!
- ✅ 无需在
requirements.txt中添加snail-job-python - ✅ 所有业务脚本可以直接
import snailjob as sj - ✅ 使用的版本与执行器保持一致
根目录依赖
项目根目录的 requirements.txt 应该只包含通用依赖:
# 根目录 requirements.txt
playwright==1.55.0
requests==2.31.0
# 注意:不需要添加 snail-job-python,会自动安装
业务特定依赖
如果业务有特定的依赖,创建业务逻辑文件夹下的 requirements.txt:
# app/services/demo_service/requirements.txt
beautifulsoup4==4.12.0
pandas==2.0.0
# 注意:不需要添加 snail-job-python,会自动安装
执行器会自动检测并安装(基于 MD5 校验,仅在变化时安装)。
依赖安装顺序
- snailjob 包(自动安装,从 PyPI)
- 根目录
requirements.txt(如果存在) - 业务目录
requirements.txt(如果存在)
在 SnailJob 中创建任务
创建步骤
- 登录 SnailJob 管理后台
- 创建新的定时任务
- 执行器类型选择:
Python - 执行器名称填入:
PlaywrightExecutor - 配置任务参数
任务参数配置
基本参数
{
"service_folder": "demo_service"
}
注意: service_folder 只需要写子文件夹名称(如 demo_service),系统会自动拼接父目录 app/services/,最终路径为 app/services/demo_service。
完整参数示例
{
"service_folder": "demo_service",
"branch": "main",
"script_timeout": 1800,
"extra_params": {
"target_url": "https://example.com",
"env": "production",
"config": {
"headless": true,
"timeout": 30
}
}
}
参数说明
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
service_folder |
string | ✅ | - | 业务逻辑子文件夹名称(只需写子文件夹名,如:demo_service)系统会自动拼接父目录 app/services/ |
branch |
string | ❌ | main | Git 分支 |
workspace_root |
string | ❌ | /workspace | 工作目录 |
script_timeout |
int | ❌ | 1800 | 脚本超时(秒) |
extra_params |
object | ❌ | {} | 传递给 run() 的参数 |
注意:
service_folder只需要写子文件夹名称(如demo_service),系统会自动拼接为app/services/demo_service- Git 仓库地址通过环境变量
GIT_REPO_URL配置,不在任务参数中传递
部署指南
本地部署
安装依赖
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt
启动执行器
python main.py
Docker 部署
构建镜像
docker build -t snail-job-playwright:latest .
运行容器
docker run -d \
--name snail-job-playwright \
--restart unless-stopped \
-e GIT_TOKEN="${GIT_TOKEN}" \
-e SNAIL_SERVER_HOST="${SNAIL_SERVER_HOST}" \
-e GIT_REPO_URL="${GIT_REPO_URL}" \
-v playwright-workspace:/workspace \
snail-job-playwright:latest
查看日志
docker logs -f snail-job-playwright
Docker Compose 部署(推荐)
启动服务
docker-compose up -d
查看日志
docker-compose logs -f
停止服务
docker-compose down
重启服务
docker-compose restart
常见问题
GitLab 相关
Q: GitLab 代码拉取失败?
A: 检查以下几点:
- 检查
GIT_TOKEN是否正确(HTTPS 方式) - 确认 GitLab 仓库权限(至少需要
read_repository权限) - 检查
GIT_REPO_URL格式是否正确 - 检查网络连接
- 如果使用 HTTPS 方式遇到限流,建议切换到 SSH 方式
Q: 如何获取 GitLab Token?
A:
- 登录 GitLab
- 进入 Settings → Access Tokens
- 创建 Personal Access Token
- 勾选
read_repository权限 - 复制生成的 Token
Q: 遇到 GnuTLS recv error (-110) 错误?
A: 这是 GitHub/GitLab HTTPS 限流导致的连接中断问题。强烈建议切换到 SSH 方式:
- 生成 SSH key:
ssh-keygen -t rsa -b 4096 - 将公钥添加到 GitHub/GitLab
- 修改
GIT_REPO_URL为 SSH 格式:git@github.com:user/repo.git - 重启容器
Q: SSH 方式配置后仍然失败?
A: 检查以下几点:
- 确认
~/.ssh/id_rsa文件存在 - 确认 SSH key 已添加到 GitHub/GitLab
- 检查 Docker Compose 中是否正确挂载了 SSH key
- 查看容器日志确认 SSH key 权限是否正确(应为 600)
- 对于自建 GitLab,可能需要手动添加 known_hosts
依赖相关
Q: 依赖安装失败?
A:
- 查看 SnailJob 日志中的详细错误信息
- 检查
requirements.txt格式是否正确 - 确认 PyPI 镜像源可访问
- 尝试使用其他镜像源
Q: 如何使用私有 PyPI 源?
A: 在业务的 requirements.txt 中指定:
--index-url https://your-pypi-server.com/simple/
--trusted-host your-pypi-server.com
your-package==1.0.0
执行相关
Q: 任务执行超时?
A:
- 调整 SnailJob 任务超时时间
- 在任务参数中设置
script_timeout增加超时时间 - 检查 Playwright 脚本是否有长时间等待
- 考虑拆分为多个小任务
Q: 虚拟环境创建失败?
A:
- 确认磁盘空间充足
- 检查 Python 版本 (需要 3.10+)
- 查看详细错误日志
- 检查文件系统权限
Q: main.py 中未找到 run() 方法?
A:
- 确保
main.py中定义了run(extra_params: dict = None) -> int - 检查方法签名是否正确
- 确认文件编码为 UTF-8
Playwright 相关
Q: 浏览器启动失败?
A:
- 确认已安装 Playwright 浏览器:
playwright install chromium - Docker 环境确认镜像中已包含浏览器依赖
- 检查系统依赖是否完整
Q: 如何处理文件上传/下载?
A:
# 文件上传
file_path = Path(__file__).parent / "data.csv"
page.set_input_files("input[type='file']", str(file_path))
# 文件下载
with page.expect_download() as download_info:
page.click("a#download-link")
download = download_info.value
download.save_as("/path/to/save/file")
日志相关
Q: 日志没有上报到 SnailJob?
A:
- 确认使用的是
sj.SnailLog.AUTO或sj.SnailLog.REMOTE - 检查 SnailJob 服务器连接是否正常
- 查看执行器日志中是否有上报错误
Q: 如何查看完整日志?
A:
- SnailJob 后台: 查看任务执行日志
- Docker:
docker-compose logs -f - 本地: 日志输出到控制台
最佳实践
代码规范
- ✅ 错误处理: 总是捕获异常并记录详细日志
- ✅ 参数验证: 在
run()方法开始时验证必需参数 - ✅ 资源清理: 确保浏览器等资源正确关闭
- ✅ 日志详细: 记录关键步骤,便于问题排查
性能优化
- ✅ 幂等性: 脚本应该支持重复执行而不产生副作用
- ✅ 超时控制: 为长时间操作设置合理的超时时间
- ✅ 依赖缓存: 利用 MD5 缓存机制,避免重复安装依赖
- ✅ 浏览器复用: 考虑在多次操作中复用浏览器实例
安全建议
- ✅ 不要将
.env文件提交到代码仓库 - ✅ GitLab Token 使用最小权限(
read_repository) - ✅ 定期轮换 Token
- ✅ 生产环境使用 Docker Secrets 或 K8s Secrets
- ✅ 敏感信息不要记录到日志中
项目组织
- ✅ 将通用工具类放在
common/目录 - ✅ 使用语义化版本管理依赖
- ✅ 为长时间任务添加进度提示
- ✅ 定期清理工作目录中的旧数据
技术栈
- Python 3.10+: 主要开发语言
- SnailJob: 分布式任务调度平台
- Playwright: 浏览器自动化框架
- GitPython: Git 仓库管理
- Docker: 容器化部署
相关链接
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rayel_rpa_executor-0.0.5.0.1.tar.gz.
File metadata
- Download URL: rayel_rpa_executor-0.0.5.0.1.tar.gz
- Upload date:
- Size: 45.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
22db99b5566215fe64116657e5e6e52c2e78ab0561d26638e5b11e5e927961c7
|
|
| MD5 |
0d4dc080de2c63368cefc7dd278fa271
|
|
| BLAKE2b-256 |
89f9fc27687e6f9226797c67fa4f59e49ccae6bbb274069690d627c4cfcbc364
|
File details
Details for the file rayel_rpa_executor-0.0.5.0.1-py3-none-any.whl.
File metadata
- Download URL: rayel_rpa_executor-0.0.5.0.1-py3-none-any.whl
- Upload date:
- Size: 50.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffacd151ce63b6d1560eefcccdfd85767bf629ab4bbd6ff9d7969a726ea33a4c
|
|
| MD5 |
5f074d8d9904ac77485b23e2fbbdb697
|
|
| BLAKE2b-256 |
eff5b02cdd5613e5d40f700dfadb3120b5e2c092c1e9e3b1143040ba63e0eed1
|