Appearance
automa 与 handler API 手册
面向注入执行环境的自定义脚本。运行时直接可用
automa与handler,无需 import。
执行方式
脚本通过 new Function('automa', 'handler', ...) 注入执行,支持顶层 await。建议每步调用携带 description,便于日志排查。
1. 通用 block 入参结构
绝大多数 handler 方法都接收一个 block 对象:
js
{
id?: string, // 可选,步骤ID;不传会自动生成
description?: string, // 可选,步骤说明(强烈建议传)
data?: { ... } // 具体方法参数
}1.1 通用选择器参数(多数 DOM 类方法适用)
data.findBy?: 'cssSelector' | 'xpath':选择器类型,默认通常是 CSS。data.selector?: string:选择器字符串。data.element?: HTMLElement:直接传元素对象(优先级通常高于 selector)。data.point?: { x: number; y: number }:坐标点击/定位。data.waitForSelector?: boolean:是否等待元素出现。data.waitSelectorTimeout?: number:等待超时(毫秒)。data.multiple?: boolean:是否匹配多个元素。
1.2 通用返回约定
为便于业务层统一处理,推荐按以下方式消费返回值:
- 布尔型方法:
true/false,用于判断步骤是否执行成功。 - 对象型方法:优先判断
success字段;无success时按业务字段判断。 - 数据型方法:直接返回目标数据(如字符串、数组、对象、数字)。
- 异常处理:所有
handler调用均可能抛出异常,建议统一使用try/catch或automa.wrapPromise。
2. automa API(preload 注入)
automa = lodash 能力 + 注入环境增强方法。
2.1 基础能力
automa.config- 含义:当前流程配置对象(窗口 ID、标题、心跳参数等)。
- 用途:日志标记、流程信息展示。
automa.diffObjects(a, b)- 含义:对象差异比较。
- 场景:检测页面数据变化、增量上报。
automa.wrapPromise(fnOrPromise)- 含义:Promise 包装,减少 try/catch 样板。
- 场景:接口或复杂步骤容错。
automa.formatTime(date, format)- 常用格式:
yyyy-MM-dd、yyyyMMdd、yyyy-MM-dd HH:mm:ss。
- 常用格式:
automa.parseTime(value)- 含义:时间解析。
automa.parseUrlParam(url)/automa.getUrlParamObject(url)- 含义:URL 参数解析。
automa.getBoundingClientRect(element)- 含义:增强版元素位置获取,适配自动化点击场景。
automa.alert(message)- 含义:预加载层消息提示。
2.2 请求监听与请求信息
automa.addApiResponseListener(urlPart, listener)- 入参:
urlPart: string:URL 包含匹配(不是完整等值匹配)。listener: (info) => void
info常见字段:url,method,statusrequestHeaders,responseHeadersresponseText,body,elapsedTime
- 说明:首次调用会注入 XHR + fetch 拦截器。
- 入参:
automa.removeApiResponseListener(urlPart, listener?)- 不传
listener时,清空该urlPart下所有监听器。
- 不传
automa.resetRequest()- 含义:将“注入前缓存的请求信息”重新回放给监听器。
- 场景:脚本初始化后补收页面早期请求。
automa.getRequestHeader(name: string)- 含义:按名称读取请求头(内部会做一次重试)。
automa.getRequestQuery(name: string)- 含义:按名称读取请求 query(内部会做一次重试)。
automa.addServerResponseListener(action, listener)- 入参:
action: stringlistener: (args: any) => any | Promise<any>
- 场景:主进程下发 server 消息给页面脚本处理。
- 入参:
3. handler API(按能力分组)
handler 是自动化动作执行器。
下面每个方法都列出:入参、返回值、注意事项、示例。
3.1 流程与日志
3.1.1 handler.start()
- 入参:无
- 返回值:
void - 用途:流程起始标记;建议在脚本开始阶段调用一次。
3.1.2 handler.controllerWorkflow(block)
- 入参:
block.type: 'start' | 'stop' | 'exec' | 'reload'block.data.url?: stringblock.data.level: string(常用:info/warning/error)block.data.status: string(常用:start/success/warning/error)block.data.message: string- 扩展:业务里常传
block.data.type: 'restart'+timeout作为 reload 策略
- 返回值:一般为执行结果对象(由主进程处理结果决定)
- 示例:
js
await handler.controllerWorkflow({
description: '异常停止流程',
type: 'stop',
data: {
url: location.href,
level: 'error',
status: 'error',
message: '关键元素缺失,停止执行'
}
});3.1.3 handler.logData(block)
- 入参:
block.data.json?: anyblock.data.type?: 'info' | 'error' | 'warning' | 'debug' | 'trace' | 'fatal' | 'success'
- 返回值:日志写入结果对象
- 建议:把关键上下文(类目、页码、日期)写进
json。
3.1.4 handler.statistics(block)
- 入参:
block.data.bizName?: stringblock.data.message?: stringblock.data.startedAt?: numberblock.data.endedAt?: number
- 返回值:统计写入结果
3.2 变量、请求、文件
3.2.1 handler.variables(block)
- 入参:
block.data.variableName?: stringblock.data.variableValue?: anyblock.data.variableAction?: 'get' | 'set' | 'delete'
- 默认行为:不传
variableAction时按读取处理。 - 返回值:变量结果对象(读取时可通过
res.value取值) - 示例:
js
await handler.variables({
description: '保存运行断点',
data: {
variableName: 'shop_progress',
variableValue: { page: 3, ts: Date.now() },
variableAction: 'set'
}
});3.2.2 handler.webhook(block)
- 入参:
block.data.url: string(必须是http/https开头)block.data.method?: stringblock.data.body?: any- 实际项目常扩展:
contentType、responseType、timeout、headers
- 返回值:主进程请求结果
- 注意:
- URL 非 http 开头会直接抛错
url error。 - 适合跨域/系统层请求,稳定性通常高于页面内
fetch。
- URL 非 http 开头会直接抛错
3.2.3 handler.http(block)
- 入参:
block.onError.retries?: number当前已重试次数(内部维护)block.onError.retryTime?: number每次重试间隔,默认3000msblock.onError.maxRetries?: number最大重试次数,默认3block.data.url: string(必填)block.data.method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'(默认POST)block.data.headers?: Record<string,string> | Array<>block.data.params?: Record<string,any> | Array<>block.data.body?: string | objectblock.data.contentType?: 'json' | 'form' | 'formData' | 'text'(默认json)block.data.autoAddHeader?: boolean(默认true,自动补 Content-Type)block.data.responseType?: 'json' | 'text' | 'blob' | 'buffer'(默认json)block.data.timeout?: number(默认5000ms,<=0视为不启用 abort)block.data.sleep?: number请求前延迟(默认随机 5-10 秒)block.data.mode?: 'cors' | 'no-cors' | 'same-origin'block.data.credentials?: 'include' | 'same-origin' | 'omit'(默认include)
- 返回值:
- 按
responseType返回:json/text/blob/arrayBuffer/Response
- 按
- 重要细节:
params会自动附加_={timestamp}防缓存。GET/HEAD不发送 body。- 失败后按重试配置自动重试。
3.2.4 handler.readFile(block)
- 入参:
block.data.path: stringblock.data.encoding?: string
- 返回值:文件内容(字符串、对象或数组,取决于文件类型与解析方式)
- 常见用法:
- 读取
api.json - 读取 Excel/CSV 输入(项目扩展能力)
- 读取
3.3 元素定位与操作
3.3.1 handler.elementExists(block)
- 入参:
- 通用选择器参数
block.data.tryCount?: numberblock.data.timeout?: number(重试间隔/等待参数)
- 返回值:
boolean
3.3.2 handler.getText(block)
- 入参:
- 通用选择器参数
block.data.regex?: stringblock.data.regexExp?: string[]block.data.prefixText?: stringblock.data.suffixText?: stringblock.data.includeTags?: booleanblock.data.useTextContent?: boolean
- 返回值:文本字符串或文本数组
3.3.3 handler.forms(block)
- 入参:
- 通用选择器参数
block.data.type?: 'text-field' | 'select' | 'checkbox' | 'radio'block.data.value?: stringblock.data.getValue?: booleanblock.data.clearValue?: booleanblock.data.delay?: number输入间隔
- 返回值:设置结果或读取值
3.3.4 handler.eventClick(block)
- 入参:
block.clickType?: 'dom' | 'electron' | 'native'(默认native)block.restoreMouse?: booleanblock.data.element?: HTMLElement(优先)block.data.point?:``- 或通用选择器参数
- 返回值:点击执行结果(
true、false或带success字段的对象) - 实现行为:
- 优先按
element点击; - 其次按
point坐标点击; - 否则根据 selector 查找后点击。
- 优先按
3.3.5 handler.hoverElement(block)
- 入参:通用选择器参数
- 返回值:执行结果
3.3.6 handler.triggerEvent(block)
- 入参:
- 通用选择器参数
block.data.eventType?: 'mouse-event' | 'keyboard-event' | 'custom'block.data.eventName?: stringblock.data.eventParams?: Record<string, any>
- 返回值:执行结果
3.3.7 handler.uploadFile(block)
- 入参:
- 通用选择器参数
block.data.filePaths: string[](必填)
- 返回值:上传执行结果
3.3.8 handler.verifySelector(block)
- 入参:通用选择器参数
- 返回值:选择器验证结果(是否可定位/定位详情)
3.3.9 handler.attributeValue(block)
- 入参:
- 通用选择器参数
block.data.attributeName: stringblock.data.attributeValue?: string(set时使用)block.data.action?: 'get' | 'set'block.data.multiple?: boolean
- 返回值:属性值或设置结果
3.3.10 handler.elementScroll(block)
- 入参:
- 通用选择器参数
block.data.smooth?: booleanblock.data.scrollIntoView?: booleanblock.data.scrollX?: numberblock.data.scrollY?: numberblock.data.incX?: booleanblock.data.incY?: boolean
- 返回值:滚动执行结果
3.3.11 handler.createElement(block)
- 入参:
block.id: string- 通用选择器参数
block.data.insertAt: 'after' | 'before' | 'next-sibling' | 'prev-sibling' | 'replace'block.data.html: stringblock.data.css?: stringblock.data.dontInjectJS?: booleanblock.data.preloadScripts?: Array<{ type: string; script: string }>block.data.automaScript?: stringblock.data.javascript?: string
- 返回值:插入结果
3.3.12 handler.saveAssets(block)
- 入参:通用选择器参数 +
multiple?: boolean - 返回值:资源保存结果(图片、链接等)
3.3.13 handler.switchTo(block)
- 入参:通用选择器参数(多用于 iframe)
- 返回值:切换结果
3.3.14 handler.link(block)
- 入参:通用选择器参数 +
openInNewTab?: boolean - 返回值:跳转结果
3.4 鼠标、键盘、交互
3.4.1 handler.mouse(block)
- 入参:
block.data.x?: numberblock.data.y?: numberblock.data.button?: 'left' | 'right' | 'middle'block.data.clickType?: 'click' | 'dblclick' | 'mousedown' | 'mouseup'
- 返回值:执行结果
3.4.2 handler.keyboard(block)
- 入参:
block.data.key?: stringblock.data.code?: stringblock.data.modifiers?: string[]
- 返回值:执行结果
3.4.3 handler.pressKey(block)
- 入参:
block.data.selector?: stringblock.data.keys?: string(组合键,使用+分隔)block.data.keysToPress?: stringblock.data.action?: 'press-key' | 'multiple-keys'block.data.pressTime?: number
- 返回值:执行结果
3.4.4 handler.drag(block)
- 入参:
block.data.fromX?: numberblock.data.fromY?: numberblock.data.toX?: numberblock.data.toY?: number- 业务脚本中也常见扩展:
startPoint/endPoint/options
- 返回值:拖拽结果(常见含
success)
3.5 截图、识别、系统与数据
3.5.1 handler.takeScreenshot(block)
- 入参:
block.options.format?: 'png' | 'jpeg'block.options.quality?: number(1-100)block.options.save?: booleanblock.data.type?: 'fullpage' | 'element' | 'recognize'block.data.selector?: string
- 返回值:截图数据或文件信息
3.5.2 handler.recognize(block)
- 入参:
block.data.image: string(base64)block.data.type?: string
- 返回值:识别结果(OCR/图像分析)
3.5.3 handler.cookie(block)
- 入参:
block.data.name?: stringblock.data.action?: 'get' | 'set' | 'delete'
- 返回值:Cookie 结果
3.5.4 handler.screen(block)
- 入参:
block.data.action?: string
- 返回值:屏幕能力执行结果
3.5.5 handler.ds(block)
- 入参:
block.data.tableName: stringblock.data.action: string(最终会作为 TypeORM Repository 方法名执行)block.data.args?: any(建议传数组,会被...args展开)
- 返回值:数据源操作结果(取决于
action) - 执行语义:
- 页面调用
handler.ds(...)后,会进入数据源执行器。 - 数据源执行器会按
action调用仓储层同名方法(等价于repository[action](...args))。
- 页面调用
- 重要约束:
- 数据源 key 使用
winId(当前流程窗口 ID),数据源不存在会抛错。 tableName必须是当前数据源里已定义的表名,否则抛错。action必须是 repository 上存在的方法,否则抛错。- 若
args不是数组,...args可能导致参数展开异常,推荐统一数组格式。
- 数据源 key 使用
推荐 action 与参数模板
save(插入/更新)args: [entityOrEntities]- 示例:
[{ id: 1, name: 'A' }]或{ id: 1, name: 'A' }
find(查询列表)args: [findOptions]- 示例:
[{ where: { shopId: 1001 }, order: { id: 'DESC' }, take: 20 }]
findOne(查询单条)args: [findOneOptions]- 示例:
[{ where: { id: 1 } }]
update(按条件更新)args: [criteria, partialEntity]- 示例:
[{ id: 1 }, { status: 'done' }]
delete(按条件删除)args: [criteria]- 示例:
[{ id: 1 }]
count(计数)args: [countOptions]- 示例:
[{ where: { status: 'done' } }]
clear(清空表)args: []
返回值参考(按 action)
save:返回保存后的实体(单条或数组)find:返回数组findOne:返回单条实体或nullupdate:返回UpdateResultdelete:返回DeleteResultcount:返回numberclear:通常返回voidclear:返回void
错误排查(高频)
DataSource with key xxx does not exist- 原因:当前流程数据源未初始化或已销毁。
- 处理:确认流程是否已创建对应数据源,再执行
ds。
Repository for table xxx does not exist- 原因:表名不在该流程的数据源配置中。
- 处理:核对
tableName与 worker/tableConfig。
Action xxx does not exist on repository- 原因:
action不是 TypeORM Repository 方法。 - 处理:改用
save/find/findOne/update/delete/count/clear等可用方法。
- 原因:
最佳实践示例
js
// 1) 写入一条采集结果
await handler.ds({
description: '写入商品数据',
data: {
tableName: 'product_daily',
action: 'save',
args: [{ productId: 123, date: '2026-04-28', click: 88 }]
}
});
// 2) 查询待处理数据
const rows = await handler.ds({
description: '查询待处理商品',
data: {
tableName: 'product_daily',
action: 'find',
args: [{ where: { synced: 0 }, take: 100 }]
}
});
// 3) 更新状态
await handler.ds({
description: '更新同步状态',
data: {
tableName: 'product_daily',
action: 'update',
args: [{ productId: 123, date: '2026-04-28' }, { synced: 1, syncedAt: Date.now() }]
}
});3.5.6 handler.loopData(block)
- 入参:
- 通用选择器参数
block.data.$frameSelector?: stringblock.data.loopId?: stringblock.onlyGenerate?: boolean
- 返回值:循环数据结果
3.5.7 handler.loopElements(block)
- 入参:
block.id: stringblock.data.$frameSelector?: stringblock.data.findBy?: 'cssSelector' | 'xpath'block.data.selector?: stringblock.data.loopAttrId?: stringblock.data.index?: numberblock.data.type?: 'scroll-down' | 'scroll-up' | 'click-element' | 'click-link'block.data.scrollToBottom?: booleanblock.data.actionElSelector?: stringblock.data.actionElMaxWaitTime?: number(秒)block.data.onlyClickLink?: boolean
- 返回值:
- 常见为“循环选择器数组”或
{ continue: true }
- 常见为“循环选择器数组”或
- 关键行为:
scroll-*:基于滚动加载新元素。click-element:点击触发加载后再采集。click-link + onlyClickLink:直接跳转链接并返回。
3.5.8 handler.delay(blockOrNumber)
- 入参:
block.delayTime?: numberblock.data.delayTime?: numberblock.data.minTime?: numberblock.data.maxTime?: number
- 返回值:
Promise<void>
3.5.9 handler.focus(block)
- 入参:无特定字段
- 返回值:聚焦结果
3.5.10 handler.getRequestHeader(block) / handler.getRequestQuery(block)
- 入参:
block.data.name?: string
- 返回值:指定请求头/请求参数值
- 说明:与
automa.getRequestHeader/getRequestQuery类似,调用链不同。
3.5.11 handler.clipboard()
- 入参:无
- 返回值:
Promise<string>,返回当前页面选中文本 - 行为说明:
- 会读取当前选区文本(
window.getSelection().toString()) - 会将选区文本写入系统剪贴板
- 会读取当前选区文本(
- 用例:
js
const copiedText = await handler.clipboard();
await handler.logData({
description: '记录复制内容',
data: { type: 'info', json: { copiedText } }
});4. 实战脚本模板(推荐)
js
/* eslint-disable no-undef */
await handler.delay({ delayTime: 1000 });
const currentUrl = `${location.origin}${location.pathname}`;
if (!currentUrl.includes('sycm.taobao.com')) return;
const state = await handler.variables({
description: '读取断点',
data: { variableName: 'sycm_progress', variableAction: 'get' }
});
const exists = await handler.elementExists({
description: '检查查询按钮',
data: { findBy: 'cssSelector', selector: '.search-btn', waitForSelector: true, waitSelectorTimeout: 8000 }
});
if (!exists) {
await handler.controllerWorkflow({
type: 'stop',
data: {
url: location.href,
level: 'error',
status: 'error',
message: '查询按钮不存在,停止流程'
}
});
return;
}
await handler.eventClick({
description: '点击查询',
clickType: 'native',
data: { findBy: 'cssSelector', selector: '.search-btn' }
});
await handler.statistics({
description: '记录成功统计',
data: {
bizName: 'SYCM脚本示例',
message: '执行成功',
startedAt: Date.now() - 5000,
endedAt: Date.now()
}
});5. 最佳实践与避坑清单
- 所有关键步骤都带
description,日志可读性会显著提升。 - 变量操作显式写
variableAction,避免隐式默认导致误解。 webhook/http请求都设置timeout和重试策略,避免流程卡死。- 涉及循环抓取时,必须落断点变量(页码/索引/日期/时间戳)。
- UI 容易抖动的页面优先用
clickType: 'native'或electron,并配合等待。 - 流程失败时优先
controllerWorkflow({ type: 'stop' | 'reload' }),不要 silent fail。 - 页面守卫统一使用
location.origin + location.pathname。
6. 方法用例总表(每个方法一个示例)
本节用于“即抄即用”。示例以最小可运行为目标,字段可按业务扩展。
6.0 方法覆盖清单
automa:config、diffObjects、wrapPromise、formatTime、parseTime、parseUrlParam、getUrlParamObject、getBoundingClientRect、alert、ipcRenderer、addApiResponseListener、removeApiResponseListener、resetRequest、getRequestHeader、getRequestQuery、addServerResponseListenerhandler:start、controllerWorkflow、logData、statistics、variables、webhook、http、readFile、elementExists、getText、forms、eventClick、hoverElement、triggerEvent、uploadFile、verifySelector、attributeValue、elementScroll、createElement、saveAssets、switchTo、link、mouse、keyboard、pressKey、drag、delay、focus、takeScreenshot、recognize、cookie、screen、ds、loopData、loopElements、getRequestHeader、getRequestQuery、clipboard
6.1 automa 方法用例
js
// automa.diffObjects
const diff = automa.diffObjects({ a: 1 }, { a: 2 });
// automa.wrapPromise
const [err, data] = await automa.wrapPromise(fetch('/api/user').then(r => r.json()));
// automa.formatTime / parseTime
const day = automa.formatTime(new Date(), 'yyyy-MM-dd');
const ts = automa.parseTime('2026-04-28 10:00:00');
// automa.parseUrlParam / getUrlParamObject
const queryStr = automa.parseUrlParam(location.href);
const queryObj = automa.getUrlParamObject(location.href);
// automa.getBoundingClientRect
const rect = await automa.getBoundingClientRect(document.body);
// automa.alert
automa.alert('脚本已启动');
// automa.getRequestHeader / getRequestQuery
const token = await automa.getRequestHeader('authorization');
const uid = await automa.getRequestQuery('uid');
// automa.addApiResponseListener / removeApiResponseListener / resetRequest
const onUser = info => console.log('user api:', info.status, info.url);
automa.addApiResponseListener('/api/user', onUser);
await automa.resetRequest();
automa.removeApiResponseListener('/api/user', onUser);
// automa.addServerResponseListener
automa.addServerResponseListener('script', async args => ({ ok: true, args }));6.2 handler 流程与日志
js
handler.start();
await handler.controllerWorkflow({
description: '结束流程',
type: 'stop',
data: { url: location.href, level: 'info', status: 'success', message: '执行完成' }
});
await handler.logData({
description: '记录关键日志',
data: { type: 'info', json: { stage: 'login', ok: true } }
});
await handler.statistics({
description: '记录统计',
data: { bizName: '登录流程', message: '成功1次', startedAt: Date.now() - 3000, endedAt: Date.now() }
});6.3 handler 数据与请求
js
// variables
await handler.variables({ data: { variableName: 'token', variableValue: 'abc', variableAction: 'set' } });
const tokenVar = await handler.variables({ data: { variableName: 'token', variableAction: 'get' } });
// webhook
const webhookRes = await handler.webhook({
data: { url: 'https://example.com/hook', method: 'POST', body: { id: 1 } }
});
// http
const httpRes = await handler.http({
data: {
url: 'https://example.com/api/list',
method: 'GET',
params: { page: 1, size: 20 },
responseType: 'json',
timeout: 8000
}
});
// readFile
const configText = await handler.readFile({ data: { path: './config/api.json', encoding: 'utf-8' } });
// ds
await handler.ds({
data: { tableName: 'orders', action: 'save', args: [{ orderId: 'A001', amount: 99.9 }] }
});
const count = await handler.ds({
data: { tableName: 'orders', action: 'count', args: [{ where: { amount: 99.9 } }] }
});6.4 handler 元素与表单
js
// elementExists
const hasSubmit = await handler.elementExists({ data: { findBy: 'cssSelector', selector: '#submit' } });
// getText
const title = await handler.getText({ data: { findBy: 'cssSelector', selector: 'h1', useTextContent: true } });
// forms
await handler.forms({
data: { findBy: 'cssSelector', selector: '#username', type: 'text-field', value: 'demo', delay: 200 }
});
// eventClick
await handler.eventClick({ clickType: 'native', data: { findBy: 'cssSelector', selector: '#submit' } });
// hoverElement
await handler.hoverElement({ data: { findBy: 'cssSelector', selector: '.menu-item' } });
// triggerEvent
await handler.triggerEvent({
data: { findBy: 'cssSelector', selector: '#btn', eventType: 'mouse-event', eventName: 'click' }
});
// uploadFile
await handler.uploadFile({
data: { findBy: 'cssSelector', selector: 'input[type=file]', filePaths: ['/tmp/a.png'] }
});
// verifySelector
const verifyRes = await handler.verifySelector({ data: { findBy: 'cssSelector', selector: '.table-row' } });
// attributeValue
const href = await handler.attributeValue({
data: { findBy: 'cssSelector', selector: 'a.detail', attributeName: 'href', action: 'get' }
});
// elementScroll
await handler.elementScroll({
data: { findBy: 'cssSelector', selector: '.list', scrollY: 500, smooth: true, incY: true }
});
// createElement
await handler.createElement({
id: 'create-tips',
data: { findBy: 'cssSelector', selector: 'body', insertAt: 'before', html: '<div id="tips">运行中</div>' }
});
// saveAssets
await handler.saveAssets({ data: { findBy: 'cssSelector', selector: 'img.preview', multiple: true } });
// switchTo
await handler.switchTo({ data: { findBy: 'cssSelector', selector: 'iframe#child' } });
// link
await handler.link({ data: { findBy: 'cssSelector', selector: 'a.next-page', openInNewTab: false } });6.5 handler 交互控制
js
// mouse
await handler.mouse({ data: { x: 300, y: 420, button: 'left', clickType: 'click' } });
// keyboard
await handler.keyboard({ data: { key: 'a', code: 'KeyA', modifiers: ['control'] } });
// pressKey
await handler.pressKey({ data: { selector: '#keyword', action: 'multiple-keys', keys: 'Control+A' } });
// drag
await handler.drag({ data: { fromX: 200, fromY: 300, toX: 600, toY: 300 } });
// delay
await handler.delay(1200);
await handler.delay({ data: { minTime: 1000, maxTime: 3000 } });
// focus
await handler.focus();6.6 handler 图像、系统与循环
js
// takeScreenshot
const shot = await handler.takeScreenshot({
options: { format: 'png', quality: 90, save: true },
data: { type: 'fullpage' }
});
// recognize
const recRes = await handler.recognize({ data: { image: 'base64-xxx', type: 'ocr' } });
// cookie
const cookieStr = await handler.cookie({ data: { action: 'get' } });
await handler.cookie({ data: { name: 'sid', action: 'delete' } });
// screen
const screenRes = await handler.screen({ data: { action: 'capture' } });
// loopData
const rows = await handler.loopData({
data: { findBy: 'cssSelector', selector: '.row', loopId: 'list-1', multiple: true }
});
// loopElements
const loopSelectors = await handler.loopElements({
id: 'loop-1',
data: {
findBy: 'cssSelector',
selector: '.goods-item',
loopAttrId: 'goods-loop',
index: 0,
type: 'scroll-down',
actionElMaxWaitTime: 3
}
});
// getRequestHeader / getRequestQuery
const reqHeader = await handler.getRequestHeader({ data: { name: 'authorization' } });
const reqQuery = await handler.getRequestQuery({ data: { name: 'token' } });
// clipboard
const copied = await handler.clipboard();