rpa 任务编排

 

image

  第三方业务系统后台数据抓取架构图

 

RPA在信也的实践

 

 

 

UpdateTaskPriority-机器人流程自动化(RPA)-阿里云帮助中心

image

 

image

 

任务状态

任务主要包括如下四种状态:

  • 等待运行:任务等待匹配机器人或正在特定机器人上排队时,显示处于等待运行的状态。

  • 正在运行:任务当前正在机器人上运行。

  • 正常结束:任务已经正常执行结束,即RPA应用顺利执行到最后,支持过程中机器人客户端没有抛出异常,但正常结束并不代表您的RPA应用完成了对应的业务结果目标。

  • 异常结束:任务执行时引擎报错,导致任务终止。可能的原因如应用执行到某个位置报错、停止任务等。

 

请求参数:

名称

类型

是否必选

示例值

描述

AppId

String

2e8e34bf -****-****-****- e1d0add3d95e

  • 应用ID。可在RPA控制台的“企业应用-企业应用列表”菜单中查看到应用ID。

说明

不同于本地型机器人的应用权限限制,服务型任务可执行本租户下所有的RPA应用。

AppParams

Array of Json,序列化方式:simple

[{"name":"参数1","value":""},{"name":"参数2","value":""}]

应用入参,执行应用所需参数。最大长度为40KB

AllocateMode

String

auto

  • 分配机器人模式,共有自动分配(auto)、手动指定(manu)两种模式

  • 为空时默认使用auto,即按照机器人分组进行自动匹配

  • 如果指定机器人运行,该入参需要为manu,并需要RobotId=<机器人ID>

PackId

String

bv2XPrDl

  • 配合AllocateMode=auto(或为空)时使用。

  • 为空默认使用服务型机器人的默认分组。

  • 如果需要指定分组,需要传入机器人分组ID。

RobotId

String

11DC81 ****** 4E463B1E538436035653

  • 配合AllocateMode=manu时使用。

  • 需要传入指定的机器人ID。

TaskPriority

Integer

85

任务优先级,整数,默认值为50。取值范围:1-100,其中100为优先级最高。

CallbackUrl

String

http://example.callback.com/example

回调地址,需要填写完整的url,支持httphttps。回调仅支持发送POST请求。

RPA服务端发起回调请求,因此需要确保RPA服务端到您的回调地址之间网络的联通。

回调最大重试次数为3次,具体结果请在控制台任务详情中查看,回调说明详见下方描述。

AppVersion

String

1.0.0

需要执行的应用的版本。为空默认使用最大版本。

 

作用:更新单个任务的优先级

路径:rpa/openapi/raas/task/UpdateTaskPriority

类型:POST

使用方式:

  • 只有等待中的任务可以被修改优先级,其他任务状态下不可修改优先级

  • 数值越大,优先级越高,会被优先执行

请求参数:

名称

类型

是否必选

示例值

描述

TaskId

String

3226a05a -****-****-****- b8fb7e4561c6

任务ID

TaskPriority

Integer

90

任务要改成的优先级,整数。取值范围:1-100。

 

 

幂等调用

功能介绍

为保障接口调用的可靠性,部分OpenAPI支持通过请求头(Header)传递唯一标识(X-Idempotent-Request-ID)的方式实现幂等性控制。该功能可避免因网络异常、重复提交等原因导致的重复请求。

 

使用方法

在发起 OpenAPI 请求时,需在请求头Header中添加以下字段:

  • 字段名(Field Name):X-Idempotent-Request-ID。

  • 字段值(Field Value):自定义的唯一字符串(推荐使用32位标准UUID)。

 

注意事项

  1. 字段长度限制:

    1. X-Idempotent-Request-ID 最大长度为50字符。

    2. 建议使用标准UUID,例如:c0e77df6-2af3-4c60-8440-abf447845491。

  2. 空值处理:

    1. 若不包含该Header,或者字段值为 null、空字符串("")或仅含空白字符(如 " "),则幂等性功能失效。

  3. 有效期限制:

    1. 有效期内重复使用相同 ID:服务器将 返回缓存的首次处理后的结果(除了requestId之外,响应体与首次一致)。

    2. 超过有效期后重复使用相同 ID:服务器将 视为新请求,正常处理并返回新结果。

 

 

作用:停止指定机器人的等待运行和正在执行的任务

路径:rpa/openapi/raas/task/ClearTaskQueue

类型:POST

使用方式:

  • 停止指定机器人的等待运行和正在运行的任务,任务状态变成异常结束

  • 该接口为异步接口,最终任务状态请以控制台展示,ListTasksListTaskDetails查询结果为准

请求参数:

名称

类型

是否必选

示例值

描述

RobotId

String

6579633 ****** D178CAC2FCBD5BD0B4EC

机器人ID(仅支持传入单个)

返回参数:

Boolean

 

 

 

 

xml

bf2514812ef472c277bbbf3cf6c860e5f99b2715f5f60d088987de44592af910_semantic_False

 

 

 

3b7515e5-b1dc-42b9-8b2b-c197cb515653

 

 33914c42-48a9-44ea-a80f-ae5fb405aa9c

 

 

<?xml version="1.0" encoding="utf-8"?>
<repository xmlns:x="rpa://selector/core" xmlns:regex="rpa://selector/operator/regex" xmlns:wildcard="rpa://selector/operator/wildcard" xmlns:contains="rpa://selector/operator/contains" xmlns:notContains="rpa://selector/operator/notContains" xmlns:startsWith="rpa://selector/operator/startsWith" xmlns:notStartsWith="rpa://selector/operator/notStartsWith" xmlns:endsWith="rpa://selector/operator/endsWith" xmlns:notEndsWith="rpa://selector/operator/notEndsWith" xmlns:notEquals="rpa://selector/operator/notEquals" xmlns:greaterThan="rpa://selector/operator/greaterThan" xmlns:greaterThanOrEqual="rpa://selector/operator/greaterThanOrEqual" xmlns:lessThan="rpa://selector/operator/lessThan" xmlns:lessThanOrEqual="rpa://selector/operator/lessThanOrEqual">
  <group id="378806ed-df52-4b4c-a7b3-1c85576bcd6a" name="影刀RPA - 影刀官网" type="Web" processName="chrome" icon=".dev\icon\0897ae0c-d077-4be7-9ad1-b51ade5872b4.png" criteria="https://www.yingdao.com" selectorOringin="Inspect">
    <selector id="50a15322-17bc-4050-8431-e8a6ab7df07b" name="姓名" type="simple" framework="chrome" selectorOringin="Inspect" processName="chrome" productName="Google Chrome" winTitle="影刀RPA - 影刀官网" screenshot=".dev\screenshot\33914c42-48a9-44ea-a80f-ae5fb405aa9c.jpg" version="2">
      <web x:name="div" x:selected="false">
        <optional id="root" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="layout___3kS5z" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="message___3jpIK" index-of-type="2" index="2" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="messageBanner___8FYNF" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="messageBannerContent___30_I0" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="bannerRight___1Nq5A" index-of-type="1" index="1" />
      </web>
      <web x:name="form">
        <optional class="ant-form ant-form-vertical contentRightForm___20vzk" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item ant-form-item-with-help ant-form-item-has-error" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-row ant-form-item-row" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional innerText="请输入姓名" class="ant-col ant-form-item-control" index-of-type="1" index="1" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item-control-input" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item-control-input-content" index-of-type="0" index="0" />
      </web>
      <web x:name="input" id="name">
        <optional type="text" class="ant-input ant-input-status-error" index-of-type="0" placeholder="请输入姓名" aria-required="true" aria-describedby="name_help" aria-invalid="true" index="0" />
      </web>
      <anchor text="姓名" targetRectangle="[740,243,396,41]" anchorRectangle="[740,215,39,20]" version="1" threshold="0.85" />
      <semantic status="disabled" image="https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/966969883689275394/file/client/element/e4600cc14891798222bb6c2e41bf5bb96a31fccf7e701856ca2ff039b7dccbe2_semantic_False.png" rectangle="[714,355,382,59]" desc="" />
    </selector>
    <selector id="ca58a85f-3d69-4459-b45d-99d6f58fc11c" name="手机号" type="simple" framework="chrome" selectorOringin="Inspect" processName="chrome" productName="Google Chrome" winTitle="影刀RPA - 影刀官网" screenshot=".dev\screenshot\3b7515e5-b1dc-42b9-8b2b-c197cb515653.jpg" version="2">
      <web x:name="div" x:selected="false">
        <optional id="root" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="layout___3kS5z" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="message___3jpIK" index-of-type="2" index="2" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="messageBanner___8FYNF" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="messageBannerContent___30_I0" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="bannerRight___1Nq5A" index-of-type="1" index="1" />
      </web>
      <web x:name="form">
        <optional class="ant-form ant-form-vertical contentRightForm___20vzk" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item ant-form-item-with-help ant-form-item-has-error" index-of-type="1" index="1" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-row ant-form-item-row" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional innerText="请输入手机号" class="ant-col ant-form-item-control" index-of-type="1" index="1" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item-control-input" index-of-type="0" index="0" />
      </web>
      <web x:name="div" x:selected="false">
        <optional class="ant-form-item-control-input-content" index-of-type="0" index="0" />
      </web>
      <web x:name="input" id="number">
        <optional type="text" class="ant-input ant-input-status-error" index-of-type="0" placeholder="请输入手机号" aria-required="true" aria-describedby="number_help" aria-invalid="true" index="0" />
      </web>
      <anchor text="手机号" targetRectangle="[740,338,396,41]" anchorRectangle="[740,310,53,20]" version="1" threshold="0.85" />
      <semantic status="disabled" image="https://winrobot-pub-a.oss-cn-hangzhou.aliyuncs.com/966969883689275394/file/client/element/bf2514812ef472c277bbbf3cf6c860e5f99b2715f5f60d088987de44592af910_semantic_False.png" rectangle="[714,495,382,59]" desc="" />
    </selector>
  </group>
</repository>

 

 

新闻列表

(() => {
  const items = [];
  const seen = new Set();
  const links = [...document.querySelectorAll("a[href*='/news/']")];
  for (const a of links) {
    const href = (a.getAttribute("href") || "").trim();
    if (!href || /\/news\/?$/.test(href.replace(location.origin, ""))) continue;
    const title = (a.innerText || a.textContent || "")
      .trim()
      .replace(/\s+/g, " ");
    if (!title || title.length < 4 || title === "查看更多") continue;
    if (seen.has(title)) continue;
    seen.add(title);
    items.push({ title, href });
  }
  const titles = items.map((item) => item.title);
  return {
    href: location.href,
    title: document.title,
    newsLinkCount: items.length,
    newsTitles: titles,
    newsItems: items,
    domNodeCount: document.querySelectorAll(
      "[class*='news'], [class*='News'], article, li"
    ).length,
    bodyHeight: document.body?.scrollHeight || 0,
  };
})()

  

https://www.yingdao.com/news/

(() => {
  const normalize = (text) => (text || "").replace(/\s+/g, "");
  const nodes = [...document.querySelectorAll("a, button, [role='button'], div, span, p")];
  const target = nodes.find((el) => {
    const text = normalize(el.textContent);
    return text === "查看更多" || (text.includes("查看更多") && text.length <= 24);
  });
  if (!target) {
    return { ok: false, reason: "not_found" };
  }
  target.scrollIntoView({ block: "center", behavior: "instant" });
  target.click();
  return {
    ok: true,
    tag: target.tagName,
    text: (target.textContent || "").trim().slice(0, 80),
  };
})()

{ok: true, tag: 'DIV', text: '查看更多'}

 

控制台里 DOM 点击仍可能无效,这是浏览器安全机制,不是脚本写错。

 

// 定位「查看更多」并尝试 DOM 点击;返回中心坐标 (x,y) 供 CDP Input 可信点击。
// 注意:控制台执行时 dispatchEvent/.click() 的 isTrusted=false,部分站点会无效果。
(() => {
  const normalize = (text) => (text || "").replace(/\s+/g, "");
  const isViewMore = (text) =>
    text === "查看更多" || (text.includes("查看更多") && text.length <= 24);

  const candidates = [...document.querySelectorAll("*")].filter((el) => {
    const text = normalize(el.textContent);
    if (!isViewMore(text)) return false;
    const rect = el.getBoundingClientRect();
    return rect.width > 0 && rect.height > 0;
  });

  if (!candidates.length) {
    return { ok: false, reason: "not_found" };
  }

  // 取文本最短的节点,避免点到外层大容器 DIV
  candidates.sort(
    (a, b) => normalize(a.textContent).length - normalize(b.textContent).length
  );

  const pickClickTarget = (el) => {
    let node = el;
    while (node && node !== document.documentElement) {
      const tag = node.tagName;
      const role = node.getAttribute?.("role");
      const style = window.getComputedStyle(node);
      if (
        tag === "A" ||
        tag === "BUTTON" ||
        role === "button" ||
        node.hasAttribute("onclick") ||
        style.cursor === "pointer"
      ) {
        return node;
      }
      node = node.parentElement;
    }
    return el;
  };

  const dispatchMouseClick = (el, x, y) => {
    const base = {
      bubbles: true,
      cancelable: true,
      view: window,
      clientX: x,
      clientY: y,
      button: 0,
      buttons: 1,
    };
    for (const type of ["pointerdown", "mousedown", "pointerup", "mouseup", "click"]) {
      const EventClass = type.startsWith("pointer") ? PointerEvent : MouseEvent;
      el.dispatchEvent(new EventClass(type, base));
    }
    if (typeof el.click === "function") {
      el.click();
    }
  };

  const base = candidates[0];
  const target = pickClickTarget(base);
  target.scrollIntoView({ block: "center", behavior: "instant" });

  const rect = target.getBoundingClientRect();
  if (rect.width <= 0 || rect.height <= 0) {
    return { ok: false, reason: "not_visible", tag: target.tagName };
  }

  const x = rect.left + rect.width / 2;
  const y = rect.top + rect.height / 2;

  // 控制台里 dispatchEvent / .click() 可能是 isTrusted=false,部分站点会忽略
  dispatchMouseClick(target, x, y);

  return {
    ok: true,
    tag: target.tagName,
    baseTag: base.tagName,
    text: (target.textContent || "").trim().slice(0, 80),
    className: String(target.className || "").slice(0, 120),
    x: Math.round(x),
    y: Math.round(y),
  };
})()

  

  

 

posted @ 2026-06-27 17:14  papering  阅读(7)  评论(0)    收藏  举报