feat: 新增通用步骤任务+元素抓取,完善全部项目文档

- 新增 generic_steps 通用步骤任务(可视化步骤编辑器编排流程,支持 open_app/click/swipe/input_text/wait/loop/group)

- 新增 core/uiauto_helper.py 封装 uiautodev 元素抓取客户端

- web_server 新增元素抓取/截图/设备列表等 API

- monitor.html 新增步骤编辑器、元素抓取模态框、独立关闭逻辑

- 新增 README.md 项目总览(快速上手/架构/配置/FAQ)

- 新增 doc/ARCHITECTURE.md 架构详解、doc/DEPLOY.md 部署指南、doc/API.md 接口文档

- 修复 doc/TASK_DEV.md:移除已删除的 comment 引用,补充 generic 包,更新注册示例

- .gitignore 忽略 .claude/ 工具产物
This commit is contained in:
2026-08-08 10:40:06 +08:00
parent 186bded9d9
commit 468e86f0a9
17 changed files with 3202 additions and 146 deletions
+33 -61
View File
@@ -42,16 +42,18 @@ platform-tools/
│ ├── __init__.py # create_action_registry / register_action / should_trigger
│ └── base.py # BaseAction 全局基类
├── tasks/ # 任务定义层
│ ├── __init__.py # 全局 _TASK_TYPES 注册表
│ ├── __init__.py # 全局 _TASK_TYPES 注册表(import 各任务包触发注册)
│ ├── base.py # BaseTask 基类
│ └── douyin/ # 抖音养号(示例)
│ ├── douyin/ # 抖音养号(示例)
│ │ ├── __init__.py
│ │ ├── task.py # DEFAULT_PARAMS + Worker + Task + @register_task
│ │ └── actions/
│ │ ├── __init__.py # 先 from .base import ACTIONS,再 from . import like
│ │ ├── base.py # ACTIONS = create_action_registry()
│ │ └── like.py # @register_action(ACTIONS) LikeAction
│ └── generic/ # 通用步骤任务(可视化步骤编辑器编排)
│ ├── __init__.py
│ ├── task.py # DEFAULT_PARAMS + Worker + Task + @register_task
│ └── actions/
│ ├── __init__.py # 先 from .base import ACTIONS,再 from . import like, comment
│ ├── base.py # ACTIONS = create_action_registry()
│ ├── like.py # @register_action(ACTIONS) LikeAction
│ └── comment.py # @register_action(ACTIONS) CommentAction
│ └── task.py # STEP_TYPES + Worker + Task(按 steps 顺序执行)
├── templates/admin/
│ ├── monitor.html # 单页应用(5 Tab,纯前端渲染)
│ └── login.html # 登录页
@@ -135,7 +137,7 @@ def get_task_class(task_type):
### 2.5 Action — 操作
`Action` 是任务循环里执行的"原子操作"(点赞 / 评论 / 滑动 / 关注)。每个 app 有**独立的 Action 注册表**(通过 `create_action_registry()` 创建),互不污染。全局基类 `core/actions/base.py::BaseAction` 提供通用能力。
`Action` 是任务循环里执行的"原子操作"(点赞 / 关注 / 滑动等)。每个 app 有**独立的 Action 注册表**(通过 `create_action_registry()` 创建),互不污染。全局基类 `core/actions/base.py::BaseAction` 提供通用能力。
### 2.6 进度上报(通用,适配任意 app)
@@ -326,7 +328,7 @@ from .base import (
# 再导入各操作模块,触发 @register_action(ACTIONS) 注册
from . import like # noqa: F401
# from . import comment # 新增 action 在此 import
# 新增 action 在此 import,例如:from . import follow
__all__ = [
"BaseAction", "register_action", "create_action_registry",
@@ -342,7 +344,7 @@ __all__ = [
"""快手养号任务定义。
本文件自包含所有快手养号参数,不依赖 core 的业务配置。
快手专属操作(点赞/评论)在 actions/ 子包里,xpath 只适用于快手。
快手专属操作(点赞/关注等)在 actions/ 子包里,xpath 只适用于快手。
"""
import time
import random
@@ -509,8 +511,9 @@ from . import task # noqa: F401 触发 @register_task 注册
```python
# tasks/__init__.py
from .base import BaseTask, register_task, list_task_types, get_task_class
from . import douyin # noqa: F401
from . import kuaishou # noqa: F401 ← 新增这一行
from .douyin import task # noqa: F401
from .generic import task # noqa: F401
from .kuaishou import task # noqa: F401 ← 新增这一行
```
完成。重启 web 后,前端任务类型下拉自动出现 `kuaishou_nurture`。
@@ -672,8 +675,10 @@ def run_task(self, d):
### 5.3 完整 Action 模板
下面以"关注"操作为例,展示一个完整 Action 的写法(多策略定位 + 概率触发 + 异常兜底):
```python
# tasks/xxx/actions/comment.py
# tasks/xxx/actions/follow.py
import time
import random
@@ -681,17 +686,16 @@ from core.actions import BaseAction, register_action, should_trigger
from core.logger import get_logger
from . import ACTIONS # 从 __init__ 导入本 app 注册表
_log = get_logger("action.xxx.comment")
_log = get_logger("action.xxx.follow")
@register_action(ACTIONS)
class CommentAction(BaseAction):
action_type = "comment"
name = "评论"
description = "看完视频后随机发一条评论"
class FollowAction(BaseAction):
action_type = "follow"
name = "关注"
description = "看完视频后随机关注作者"
default_params = {
"rate": 0.1,
"texts": ["不错", "666", "学到了"],
}
def execute(self, d, params, worker):
@@ -699,51 +703,19 @@ class CommentAction(BaseAction):
if not should_trigger(rate):
return False
texts = params.get("texts") or ["不错"]
text = random.choice(texts)
# 定位评论按钮(多策略组合,失败回退)
for desc in ("评论", "未评论", "comment"):
# 定位关注按钮(多策略组合,失败回退)
for desc in ("关注", "未关注", "follow"):
el = d(description=desc)
if el.exists:
el.click()
break
else:
_log.info("未找到评论按钮")
_log.info("未找到关注按钮")
return False
time.sleep(1.5)
# 找输入框
for rid in ("com.xxx:id/comment_input",):
el = d(resourceId=rid)
if el.exists:
el.click()
break
else:
d.press("back")
return False
time.sleep(0.8)
# 输入文本(中文需切输入法)
try:
d.set_fastinput_ime(True)
except Exception:
pass
d.send_keys(text)
time.sleep(0.6)
# 发送
el = d(text="发送")
if el.exists:
el.click()
_log.info(f"评论成功: {text}")
time.sleep(1.0)
d.press("back")
return True
d.press("back")
return False
time.sleep(1.0)
_log.info("关注成功")
return True
```
> **返回值约定**:`True`=成功执行;`False`=主动跳过(概率未中、元素不存在等);抛异常=执行失败,由 Worker 捕获并记录。
@@ -931,10 +903,10 @@ d.xpath('//FrameLayout[2]/LinearLayout[1]/TextView[3]').click()
```python
# tasks/xxx/actions/__init__.py
from .base import ACTIONS, ... # 1. 先建注册表
from . import like, comment # 2. 再导入各 action,触发 @register_action
from . import like # 2. 再导入各 action,触发 @register_action
```
`tasks/__init__.py` 同理:先 `from .base import BaseTask`,再 `from . import douyin`。
`tasks/__init__.py` 同理:先 `from .base import BaseTask`,再 `from . import douyin`、`from . import generic`。
### 10.2 中文输入
@@ -1036,7 +1008,7 @@ self.set_progress(videos_watched=5, round_idx=3)
- [ ] `tasks/<app>/actions/__init__.py` 先 `from .base import ACTIONS` 再导入各 action
- [ ] 每个 Action 有 `action_type` / `name` / `default_params` / `execute`,返回 `True/False`
- [ ] `Task.create_worker` 做 actions 参数级深合并(照抄抖音模板)
- [ ] `tasks/__init__.py` 已 `from . import <app>` 注册
- [ ] `tasks/__init__.py` 已 `from .<app> import task` 注册
- [ ] 日志用 `get_logger("task.<app>")` / `get_logger("action.<app>.<name>")`,无 `print`
- [ ] 定位元素优先 `description` / `descriptionContains`,resourceId 多候选,xpath 用相对定位
- [ ] 中文输入用 `set_fastinput_ime`,加 try/except