Skip to main content

a high performance distributed task scheduler and retry management center

Project description

snail-job-Logo

🎭 基于 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)

配置步骤

  1. 生成 SSH key(如果还没有):

    ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
    
  2. 将公钥添加到 GitHub/GitLab

    # 复制公钥内容
    cat ~/.ssh/id_rsa.pub
    
    • GitHub: Settings → SSH and GPG keys → New SSH key
    • GitLab: Settings → SSH Keys → Add SSH Key
  3. 修改 .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
    
  4. 确保 SSH key 文件存在

    # 检查文件是否存在
    ls -la ~/.ssh/id_rsa
    
    # 如果不存在,请先生成 SSH key
    
  5. 重启容器

    docker-compose down
    docker-compose up -d
    

注意事项

  • 确保宿主机 ~/.ssh/id_rsa 文件存在且已添加到 GitHub/GitLab
  • Docker Compose 会自动挂载 ~/.ssh/id_rsa 到容器中
  • 对于自建 GitLab,如果首次连接,可能需要手动添加 known_hosts

方式二:HTTPS 方式

适用场景

  • 临时使用或测试环境
  • 无法配置 SSH key 的环境

配置步骤

  1. 获取 Git Token

    • GitHub: Settings → Developer settings → Personal access tokens → Generate new token
    • GitLab: Settings → Access Tokens → Create personal access token
  2. 修改 .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 校验,仅在变化时安装)。

依赖安装顺序

  1. snailjob 包(自动安装,从 PyPI)
  2. 根目录 requirements.txt(如果存在)
  3. 业务目录 requirements.txt(如果存在)

在 SnailJob 中创建任务

创建步骤

  1. 登录 SnailJob 管理后台
  2. 创建新的定时任务
  3. 执行器类型选择:Python
  4. 执行器名称填入:PlaywrightExecutor
  5. 配置任务参数

任务参数配置

基本参数

{
  "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:

  1. 登录 GitLab
  2. 进入 Settings → Access Tokens
  3. 创建 Personal Access Token
  4. 勾选 read_repository 权限
  5. 复制生成的 Token

Q: 遇到 GnuTLS recv error (-110) 错误?

A: 这是 GitHub/GitLab HTTPS 限流导致的连接中断问题。强烈建议切换到 SSH 方式

  1. 生成 SSH key:ssh-keygen -t rsa -b 4096
  2. 将公钥添加到 GitHub/GitLab
  3. 修改 GIT_REPO_URL 为 SSH 格式:git@github.com:user/repo.git
  4. 重启容器

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.AUTOsj.SnailLog.REMOTE
  • 检查 SnailJob 服务器连接是否正常
  • 查看执行器日志中是否有上报错误

Q: 如何查看完整日志?

A:

  • SnailJob 后台: 查看任务执行日志
  • Docker: docker-compose logs -f
  • 本地: 日志输出到控制台

最佳实践

代码规范

  1. 错误处理: 总是捕获异常并记录详细日志
  2. 参数验证: 在 run() 方法开始时验证必需参数
  3. 资源清理: 确保浏览器等资源正确关闭
  4. 日志详细: 记录关键步骤,便于问题排查

性能优化

  1. 幂等性: 脚本应该支持重复执行而不产生副作用
  2. 超时控制: 为长时间操作设置合理的超时时间
  3. 依赖缓存: 利用 MD5 缓存机制,避免重复安装依赖
  4. 浏览器复用: 考虑在多次操作中复用浏览器实例

安全建议

  1. ✅ 不要将 .env 文件提交到代码仓库
  2. ✅ GitLab Token 使用最小权限(read_repository
  3. ✅ 定期轮换 Token
  4. ✅ 生产环境使用 Docker Secrets 或 K8s Secrets
  5. ✅ 敏感信息不要记录到日志中

项目组织

  1. ✅ 将通用工具类放在 common/ 目录
  2. ✅ 使用语义化版本管理依赖
  3. ✅ 为长时间任务添加进度提示
  4. ✅ 定期清理工作目录中的旧数据

技术栈

  • Python 3.10+: 主要开发语言
  • SnailJob: 分布式任务调度平台
  • Playwright: 浏览器自动化框架
  • GitPython: Git 仓库管理
  • Docker: 容器化部署

相关链接

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rayel_rpa_executor-0.0.5.0.2.tar.gz (45.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rayel_rpa_executor-0.0.5.0.2-py3-none-any.whl (50.5 kB view details)

Uploaded Python 3

File details

Details for the file rayel_rpa_executor-0.0.5.0.2.tar.gz.

File metadata

  • Download URL: rayel_rpa_executor-0.0.5.0.2.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

Hashes for rayel_rpa_executor-0.0.5.0.2.tar.gz
Algorithm Hash digest
SHA256 902c0010f5845bdf59444fecc5986d2a86b53ccbc5397040895a86ca03f381a5
MD5 20230fa196ff99a2c051cb0f66688e79
BLAKE2b-256 5090f83eecd4ea899943ea059fb324151917d9b2bd5d6669b3818c52984cf200

See more details on using hashes here.

File details

Details for the file rayel_rpa_executor-0.0.5.0.2-py3-none-any.whl.

File metadata

File hashes

Hashes for rayel_rpa_executor-0.0.5.0.2-py3-none-any.whl
Algorithm Hash digest
SHA256 610f7ca1dc538ef5fcfbf4ce1a804bdc7735339b9c6524354eeac66128bcd79a
MD5 82e6bfef2b76444842b329bfbf210ba2
BLAKE2b-256 e1844c9ff3b9285525e10a26a172e09936a4ceab106e46fcacff046a1f00afc6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page