rpa 任务编排

 

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  阅读(3)  评论(0)    收藏  举报