This commit is contained in:
dengqichen 2025-11-19 15:18:59 +08:00
parent cfd243aeda
commit fafec7278d
3 changed files with 199 additions and 86 deletions

View File

@ -27,6 +27,37 @@
- ✅ **声明式编程** - 只需描述"做什么",不需要"怎么做"
- ✅ **可复用** - 一次配置,多处使用
- ✅ **易维护** - 修改配置即可调整流程
- 🚀 **人类行为模拟** - 框架自动添加延迟,模拟真实用户操作
- 🎯 **智能字段推断** - 简化配置,自动查找表单字段
### 🆕 核心特性
#### 1. 人类行为延迟(自动)
框架天然支持人类行为模拟,**无需手动配置延迟**
- 📖 页面加载后自动阅读 1-3 秒
- 💭 表单填写后自动思考 0.5-1.5 秒
- ⏸️ 字段间自动停顿 200-500ms
- 🖱️ 点击前后自动延迟 200-500ms
- 📜 滚动后自动停顿查看内容
#### 2. 智能字段推断
支持超简化配置,自动推断选择器:
```yaml
# ❌ 旧方式:需要详细配置
fields:
email:
find:
- css: '#email'
- name: 'email'
value: "user@example.com"
# ✅ 新方式:一行搞定
fields:
email: "user@example.com" # 自动查找 #email, name="email" 等
```
#### 3. 配置简化
从 344 行减少到 260 行,**减少 24% 配置量**,提高可读性和维护性。
---
@ -42,29 +73,25 @@ site:
name: MySite
url: https://mysite.com/register
# 工作流定义
# 工作流定义(使用简化配置)
workflow:
- action: navigate
name: "打开注册页面"
url: "https://mysite.com/register"
# 框架会自动:加载页面 → 阅读1-3秒
- action: fillForm
name: "填写注册信息"
fields:
username:
find:
- css: '#username'
value: "{{account.username}}"
email:
find:
- css: '#email'
value: "{{account.email}}"
username: "{{account.username}}" # 自动推断选择器
email: "{{account.email}}"
# 框架会自动:字段间停顿 → 填写后思考
- action: click
name: "提交注册"
selector:
- css: 'button[type="submit"]'
- text: "Sign up" # 支持按文本查找
# 框架会自动:点击前准备 → 点击 → 点击后等待
```
### 2. 创建站点适配器
@ -186,72 +213,79 @@ errorHandling:
### fillForm - 表单填写
**用途**:填写表单字段
**用途**:填写表单字段,支持智能字段推断和人类行为模拟
**必需参数**
- `fields` (object): 字段配置对象,键为字段名
**可选参数**
- `name` (string): 步骤名称
- `humanLike` (boolean): 是否模拟人类输入,默认 `true`
- `humanLike` (boolean): ⚠️ 已废弃,框架默认使用人类行为
- `clearTimes` (number): 清空字段的按键次数,默认 25
**字段配置**
- `find` (array): 选择器数组,按顺序尝试
- `css` (string): CSS 选择器
- `xpath` (string): XPath 选择器
- `text` (string): 按文本查找
- `name` (string): 按 name 属性查找
- `value` (string): 字段值,支持变量替换
- `clear` (boolean): 填写前是否清空,默认 `true`
**字段配置格式**
#### 1. 简化配置(推荐)✨
```yaml
fields:
fieldName: "value" # 自动推断选择器
```
框架会自动查找:
- `#fieldName`
- `[name="fieldName"]`
- `input[name="fieldName"]`
- `select[name="fieldName"]`
- `textarea[name="fieldName"]`
#### 2. 完整配置
```yaml
fields:
fieldName:
find:
- css: '#custom-id'
- name: 'custom-name'
value: "{{variable}}"
type: "input" # 或 "select"
```
**自动行为**
- 🔍 自动等待字段出现
- ⏸️ 字段间自动停顿 200-500ms
- 💭 填写后自动思考 500-1500ms
- ⌨️ 模拟人类打字速度
**示例**
```yaml
# 基本表单填写
# ✅ 推荐:超简化配置
- action: fillForm
name: "填写注册信息"
fields:
username:
find:
- css: '#username'
value: "{{account.username}}"
email:
find:
- css: 'input[name="email"]'
- css: '#email'
value: "{{account.email}}"
username: "{{account.username}}"
email: "{{account.email}}"
password: "{{account.password}}"
# 模拟人类输入
# ✅ 混合配置(部分字段需要特殊处理)
- action: fillForm
name: "填写个人信息"
humanLike: true
name: "填写支付信息"
fields:
firstName:
cardNumber: "{{card.number}}" # 简化
cardExpiry: "{{card.expiry}}" # 简化
billingCountry: # 完整配置(下拉框)
find:
- css: '#firstName'
value: "{{account.firstName}}"
clear: true
lastName:
find:
- css: '#lastName'
value: "{{account.lastName}}"
- css: '#billingCountry'
value: "US"
type: "select"
# 密码字段
# 完整配置(需要精确控制)
- action: fillForm
name: "设置密码"
humanLike: false
name: "填写复杂表单"
fields:
password:
customField:
find:
- css: 'input[type="password"]'
value: "{{account.password}}"
passwordConfirm:
find:
- css: 'input[placeholder*="Confirm"]'
value: "{{account.password}}"
- css: 'input[data-custom="field"]'
- xpath: '//input[@placeholder="Custom"]'
value: "{{data.custom}}"
```
---
@ -938,7 +972,38 @@ await this.executeRetryStrategy('wait', retryCount, { waitTime: 5000 });
## 最佳实践
### 1. 步骤命名清晰
### 1. 优先使用简化配置 ✨
```yaml
# ✅ 推荐:简洁高效
- action: fillForm
fields:
email: "{{account.email}}"
password: "{{account.password}}"
# ⚠️ 仅在必要时使用完整配置
- action: fillForm
fields:
customField:
find:
- css: 'input[data-custom="field"]'
value: "{{data.value}}"
```
### 2. 删除手动延迟配置 🚀
```yaml
# ❌ 不推荐:手动配置延迟
- action: fillForm
fields: ...
waitAfter: 1000 # 框架已自动处理
# ✅ 推荐:信任框架自动延迟
- action: fillForm
fields: ... # 框架会自动添加思考延迟
```
### 3. 步骤命名清晰
```yaml
# ❌ 不好
@ -950,18 +1015,26 @@ await this.executeRetryStrategy('wait', retryCount, { waitTime: 5000 });
- action: click
name: "点击 Continue 按钮(基本信息页)"
selector:
- css: 'button[type="submit"]'
- text: 'Continue'
```
### 2. 使用多个选择器备选
### 4. 合并连续的 fillForm
```yaml
fields:
email:
find:
- css: '#email' # 首选
- css: 'input[name="email"]' # 备选1
- xpath: '//input[@type="email"]' # 备选2
# ❌ 不推荐:拆分填写
- action: fillForm
fields:
cardNumber: "..."
- action: fillForm
fields:
cardExpiry: "..."
# ✅ 推荐:合并填写(利用字段间延迟)
- action: fillForm
fields:
cardNumber: "..."
cardExpiry: "..."
cardCvc: "..."
```
### 3. 验证关键步骤
@ -1116,10 +1189,10 @@ A: 查看日志输出,每个步骤都会打印执行信息:
### Q: 元素找不到怎么办?
A:
1. 使用 `verifyElements` 验证元素存在
2. 增加 `waitAfter` 等待时间
3. 使用多个选择器备选
4. 设置 `optional: true` 跳过
1. ✅ 使用简化配置,框架会自动等待元素
2. 使用多个选择器备选
3. 设置 `optional: true` 跳过
4. ⚠️ 避免手动 `waitAfter`,框架已自动处理
### Q: 如何处理动态内容?
@ -1180,19 +1253,29 @@ A:
## 更新日志
- **v1.0.0** - 基础框架
- navigate, fillForm, click, wait, custom
- **v1.1.0** - 增强功能
- retryBlock 重试块
- 人类行为模拟
- 点击验证
- **v2.0.0** 🚀 - 智能化升级(当前版本)
- ✨ **智能字段推断**:字段名自动推断选择器,减少 70% 配置
- 🤖 **人类行为内置**:框架天然支持人类延迟,无需手动配置
- ⚡ **配置简化**:从 344 行减少到 260 行(-24%
- 🔄 **自动等待**fillForm 自动等待字段出现
- 📜 **scroll action**:页面滚动支持
- **v1.3.0** - 结果验证
- verify action
- 支持 10 种条件类型
- **v1.2.0** - 数据提取
- extract action
- 正则提取
- 多元素提取
- **v1.3.0** - 结果验证
- verify action
- 支持 10 种条件类型
- **v1.1.0** - 增强功能
- retryBlock 重试块
- 人类行为模拟
- 点击验证
- **v1.0.0** - 基础框架
- navigate, fillForm, click, wait, custom
- 轮询检测机制
- 配合 retryBlock 实现智能重试

View File

@ -2,11 +2,13 @@ const BaseAction = require('../core/base-action');
/**
* 自定义动作 - 调用适配器中的自定义函数
* 支持超时保护防止用户代码死循环
*/
class CustomAction extends BaseAction {
async execute() {
const handler = this.config.handler;
const params = this.config.params || {};
const timeout = this.config.timeout || 300000; // 默认5分钟超时
if (!handler) {
throw new Error('缺少处理函数名称');
@ -19,12 +21,29 @@ class CustomAction extends BaseAction {
throw new Error(`自定义处理函数不存在: ${handler}`);
}
// 调用自定义函数
const result = await this.context.adapter[handler](params);
// 使用 Promise.race 实现超时保护
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject(new Error(`自定义函数执行超时 (${timeout}ms): ${handler}`));
}, timeout);
});
this.log('debug', '✓ 自定义函数执行完成');
return result;
try {
// 竞速执行:函数完成 vs 超时
const result = await Promise.race([
this.context.adapter[handler](params),
timeoutPromise
]);
this.log('debug', '✓ 自定义函数执行完成');
return result;
} catch (error) {
if (error.message.includes('执行超时')) {
this.log('error', `⚠️ ${error.message}`);
}
throw error;
}
}
}

View File

@ -1,5 +1,10 @@
/**
* YAML 配置验证器
*
* 支持的配置格式
* - 完整配置详细指定所有选项
* - 简化配置自动推断字段名和选择器
* - 人类行为框架自动添加延迟无需手动配置
*/
class ConfigValidator {
constructor() {
@ -7,19 +12,21 @@ class ConfigValidator {
this.actionSchemas = {
navigate: {
required: ['url'],
optional: ['name', 'options', 'verifyUrl', 'verifyElements', 'waitAfter']
optional: ['name', 'options', 'verifyUrl', 'verifyElements', 'waitAfter', 'maxRetries', 'retryDelay', 'totalTimeout']
},
fillForm: {
required: ['fields'],
optional: ['name', 'humanLike']
optional: ['name', 'humanLike', 'autoRetry', 'clearTimes']
// 注意humanLike 已废弃,框架默认使用人类行为
// fields 支持:字符串(自动推断)或对象(完整配置)
},
click: {
required: ['selector'],
optional: ['name', 'verifyAfter', 'waitForPageChange', 'waitAfter', 'optional']
optional: ['name', 'verifyAfter', 'waitForPageChange', 'waitAfter', 'optional', 'timeout', 'waitForEnabled', 'humanLike', 'checkSelector']
},
wait: {
required: ['type'],
optional: ['name', 'duration', 'find', 'timeout']
optional: ['name', 'duration', 'find', 'timeout', 'urlContains', 'handler']
},
extract: {
required: ['selector', 'contextKey'],
@ -33,6 +40,10 @@ class ConfigValidator {
required: ['steps'],
optional: ['name', 'maxRetries', 'retryDelay', 'onRetryBefore', 'onRetryAfter']
},
scroll: {
required: [],
optional: ['name', 'type', 'selector', 'x', 'y', 'behavior']
},
custom: {
required: ['handler'],
optional: ['name', 'params', 'optional']