源码教程:DOM、页面状态与元素读取
浏览器服务把 DOM 变为可供模型阅读的文本,同时保存索引与元素、frame 的对应关系。索引是一次快照的定位线索,不是网站自己的元素 ID。
1. DOM 采集链
DomService.buildExpression 读取 resources/dom/dom_tree/index.js 与 run.js,组合并缓存执行脚本。getFrameState 将脚本分别放到对应 Frame 执行,再把结果解析为 DOMState、DOMElementNode、DOMTextNode 和 FrameSnapshot。
Page 的 frame 列表
→ 每个 Frame 执行采集脚本
→ 可见性、交互性、实时表单属性、文本及定位信息
→ 分配不重叠的索引范围
→ Java DOM 模型和 frame 映射
→ 文本渲染、交互元素表、截图与快照存储
可见性、是否可交互以及可否接收点击是不同概念。采集需要考虑布局、视口及扩展范围;点击时仍需检查遮挡。密码属性输出为脱敏标记,但这不意味着截图、URL 和普通输入框都被脱敏。
get_browser_state 默认读取主文档及可处理的同源 frame,includeFrames:true 将跨域 frame 也纳入。各 frame 共享一个全局索引空间,按索引操作时通过映射回到正确 Frame;不能拿子 frame 内的 XPath 在主文档执行。
{"id":"1001","method":"get_browser_state","params":{"includeFrames":true,"highlight":false,"viewportExpansion":800,"includeElements":true,"maxElements":100}}
maxElements 控制响应内联元素数量,不应被当作整个 DOM 的元素总数。视口外找不到控件时,先检查滚动距离和视口扩展,再决定滚动或使用选择器。
快照一致性与索引有效性
当前实现比较采集前后的页面标记,返回 snapshotConsistent、snapshotAttempts、indicesUsable 和 pageAppearsBlank。发现页面变化或部分读取失败时会清除任务快照、作废索引,并有限重取;仍不一致时补充 snapshotIssues、snapshotHint 等诊断信息。
调用方必须检查 indicesUsable,不能仅看 ok:true 就使用索引。遇到 false 时等待目标内容后重新获取状态;pageAppearsBlank 只是此次文本为空的提示,不能直接认定网站没有内容或业务已经失败。
2. 页面级读取各有用途
| 命令 | 实现与结果 |
|---|---|
get_browser_state | 生成 DOM 快照,保存索引,返回页面文本、页签和元素信息,并留档 |
list_frames | 列出当前页面 frame 的序号、地址等信息;refresh 控制相关刷新行为 |
get_page_snapshot | 汇总页面快照,可附控制台和请求信息,便于一次获取诊断上下文 |
diff_dom_text | 重新生成快照,与之前的文本按行比较;它会更新快照,不是单纯读取旧缓存 |
get_interactive_map | 返回当前可交互元素映射,适合检查完整定位信息 |
get_form_state | 遍历表单控件,读取实时 value、checked、disabled、readonly、错误提示等;可限制 selector、隐藏项和数量 |
extract_structured_data | 当前实现读取 document.body.innerText,按选项收集链接;query 被保留为结果信息,不在此命令中调用大模型抽取 |
旧的“把网页转 Markdown 再请求大模型”属于另一种设计,不是当前 extractStructuredData 的执行链。不要把命令名中的 structured 当成“已经按 query 生成业务 JSON”。如需特定结构,应在上层明确增加解析或模型步骤。
3. 元素读取共用 read 包装
多数读取方法调用 read(browserId, index, action, resultKey, reader):先找任务与索引,再执行读取函数,最后将结果写到指定 data 字段。下面是当前源码的调用形式:
return read(browserId, index, "get_element_value", "value",
locator -> locator.inputValue());
| 命令 | 底层读取 | 主要结果字段 |
|---|---|---|
get_element_text | Locator.innerText() | text |
get_element_html | Locator.innerHTML(),不是 outerHTML | html |
get_element_value | Locator.inputValue() | value |
get_element_attribute | Locator.getAttribute(name) | value |
is_visible | Locator.isVisible() | visible |
is_enabled | Locator.isEnabled() | enabled |
is_checked | Locator.isChecked() | checked |
get_element_count | 指定 Frame 内按 selector 统计 | 数量结果;无匹配与调用失败要区分 |
get_element_box | 获取元素 bounding box | 坐标与尺寸;无布局信息时不能虚构坐标 |
get_element_listeners | ListenerProbe 尝试协议探测和框架线索 | found、监听信息及检测说明;未知不等于没有监听 |
inputValue 与 HTML attribute 不同:用户修改输入框后,初始 value 属性可能没变。状态读取必须使用适合控件的实时属性。对非表单元素调用 inputValue、对非复选控件调用 isChecked,也可能因类型不匹配失败。
4. 索引生命周期与验证
在页面更新、导航或页签切换后重新取快照。即使新页面也有索引 8,它也不一定是上次的索引 8。实现中的旧快照提示和 frame 映射旨在帮助排障,不提供跨任意页面变更的稳定句柄。
本地 fixture 应包含输入框、复选框、隐藏字段、只读控件和 iframe。修改 property 后验证文本和 get_form_state 显示新值;验证密码脱敏、子 frame 索引不冲突,以及 get_element_html 只返回内部 HTML。另用两段等长文本测试差异检测,避免只比较字符串长度。
注册参数与 Java 入口
以下按 CommandTable 实际读取参数整理。* 表示注册层使用必填读取器;其余字段省略后由服务决定默认行为。带条件的入口仍需满足正文说明,例如上传文件来源、元素定位二选一。外层 id 不重复列出。
| 命令 | params 字段 | Java 入口 |
|---|---|---|
get_browser_state | highlight、viewportExpansion、includeElements、maxElements、includeFrames | getBrowserState |
list_frames | refresh | listFrames |
get_page_snapshot | includeConsole、includeRequests、requestFilter | getPageSnapshot |
diff_dom_text | highlight、viewportExpansion | diffDomText |
get_interactive_map | 无 | getInteractiveMap |
get_form_state | selector、includeHidden、max | getFormState |
extract_structured_data | query、extractLinks | extractStructuredData |
get_element_text | index* | getElementText |
get_element_html | index* | getElementHtml |
get_element_value | index* | getElementValue |
get_element_attribute | index、name | getElementAttribute |
get_element_listeners | index、selector、frame | getElementListeners |
get_element_count | selector*、frame | getElementCount |
get_element_box | index* | getElementBox |
is_visible | index* | isVisible |
is_enabled | index* | isEnabled |
is_checked | index* | isChecked |
当前源码:命令注册与执行
先在本章上半部分理解行为,再按命令展开实现。注册代码说明 JSON 参数如何传给 Java;服务方法展示实际浏览器操作。方法依赖共享类中的字段和辅助函数,不应脱离原类直接粘贴编译。
get_browser_state
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_browser_state",
(svc, id, a) -> svc.getBrowserState(id, a.getBoolean("highlight"), a.getInteger("viewportExpansion"),
a.getBoolean("includeElements"), a.getInteger("maxElements"), a.getBoolean("includeFrames")));
展开 getBrowserState 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getBrowserState(Long browserId, Boolean highlight, Integer viewportExpansion,
Boolean includeElements, Integer maxElements, Boolean includeFrames) {
return getBrowserStateAttempt(browserId, highlight, viewportExpansion, includeElements, maxElements, includeFrames, 1);
}
list_frames
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("list_frames", (svc, id, a) -> svc.listFrames(id, a.getBoolean("refresh")));
展开 listFrames 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo listFrames(Long browserId, Boolean refresh) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
boolean rebuild = refresh == null || refresh;
if (rebuild) {
try {
recordSnapshot(inst, DomService.getFrameState(inst.page, false, 0));
} catch (PlaywrightException e) {
return RespBodyVo.fail("list_frames 失败:读取页面 frame 失败(" + briefMessage(e.getMessage()) + ")");
}
}
List<Kv> frames = frameList(inst.domState);
if (frames.isEmpty()) {
// 快照不是带 frame 的那种时,至少把 frame 的 URL/名称给出来,别让调用方以为「一个 frame 都没有」
for (DomService.FrameNode node : DomService.frameTree(inst.page)) {
Kv item = Kv.by("index", frames.size()).set("url", safeFrameUrl(node.frame))
.set("name", safeFrameName(node.frame)).set("isMain", node.parentIndex < 0).set("depth", node.depth);
if (node.parentIndex >= 0) {
item.set("parentIndex", node.parentIndex);
}
frames.add(item);
}
}
Kv data = Kv.by("count", frames.size()).set("frames", frames)
.set("note", "index 0 是主 frame;跨域 iframe 也能读到 URL(这是识别它的主要依据)。"
+ "要读 iframe 里的元素用 get_browser_state 的 includeFrames:true");
return RespBodyVo.ok(data);
}
get_page_snapshot
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_page_snapshot", (svc, id, a) -> svc.getPageSnapshot(id, a.getBoolean("includeConsole"),
a.getBoolean("includeRequests"), optStr(a, "requestFilter")));
展开 getPageSnapshot 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getPageSnapshot(Long browserId, Boolean includeConsole, Boolean includeRequests,
String requestFilter) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
Kv kv = Kv.by("url", inst.page.url()).set("title", safeTitle(inst.page)).set("tabs", tabs(inst))
.set("dialog", inst.lastDialog).set("loading", isPageLoading(inst));
if (includeConsole != null && includeConsole) {
kv.set("logs", new ArrayList<>(inst.consoleLogs));
kv.set("errors", new ArrayList<>(inst.pageErrors));
}
if (includeRequests != null && includeRequests) {
kv.set("requests", filterRequests(inst, requestFilter));
}
return RespBodyVo.ok(kv);
}
diff_dom_text
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("diff_dom_text",
(svc, id, a) -> svc.diffDomText(id, a.getBoolean("highlight"), a.getInteger("viewportExpansion")));
展开 diffDomText 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo diffDomText(Long browserId, Boolean highlight, Integer viewportExpansion) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
String previous = inst.lastDomText;
RespBodyVo current = buildState(inst, highlight, viewportExpansion);
if (!current.isOk() || !(current.getData() instanceof Kv)) {
return current;
}
Kv data = (Kv) current.getData();
String text = data.getStr("text");
Kv diff = Kv.by("url", data.get("url")).set("title", data.get("title")).set("tabs", data.get("tabs"));
if (previous == null) {
diff.set("first", true).set("changed", true).set("added", firstLines(text)).set("removed", new ArrayList<>());
return RespBodyVo.ok(diff);
}
Map<String, Integer> before = countLines(previous);
Map<String, Integer> after = countLines(text);
List<String> added = new ArrayList<>();
List<String> removed = new ArrayList<>();
for (Map.Entry<String, Integer> entry : after.entrySet()) {
int delta = entry.getValue() - before.getOrDefault(entry.getKey(), 0);
for (int i = 0; i < delta && added.size() < MAX_DIFF_LINES; i++) {
added.add(entry.getKey());
}
}
for (Map.Entry<String, Integer> entry : before.entrySet()) {
int delta = entry.getValue() - after.getOrDefault(entry.getKey(), 0);
for (int i = 0; i < delta && removed.size() < MAX_DIFF_LINES; i++) {
removed.add(entry.getKey());
}
}
diff.set("first", false).set("changed", !added.isEmpty() || !removed.isEmpty());
diff.set("added", added).set("removed", removed);
return RespBodyVo.ok(diff);
}
get_interactive_map
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_interactive_map", (svc, id, a) -> svc.getInteractiveMap(id));
展开 getInteractiveMap 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getInteractiveMap(Long browserId) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
if (inst.domState == null) {
// 以前这里直接失败,要求调用方「先调 get_browser_state」——多一次往返,而且很容易漏。
// 索引本来就是本命令的产物,自己建一次快照即可(不落盘,不产生截图/文本垃圾文件)。
RespBodyVo built = buildState(inst, false, 0);
if (!built.isOk()) {
return built;
}
}
List<Kv> items = interactiveElements(inst);
return RespBodyVo.ok(Kv.by("count", items.size()).set("elements", items)
.set("source", "get_browser_state 快照(索引与 click_element_by_index / input_text / "
+ "check_element_by_index 等按索引命令共用)"));
}
get_form_state
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_form_state", (svc, id, a) -> svc.getFormState(id, optStr(a, "selector"), a.getBoolean("includeHidden"),
a.getInteger("max")));
展开 getFormState 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getFormState(Long browserId, String selector, Boolean includeHidden, Integer max) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
JSONObject args = new JSONObject();
args.put("selector", selector);
args.put("includeHidden", includeHidden != null && includeHidden);
args.put("max", max == null || max <= 0 ? 200 : max);
Object result;
try {
result = inst.page.evaluate(FORM_STATE, args);
} catch (PlaywrightException e) {
return RespBodyVo.fail("get_form_state 失败:" + briefMessage(e.getMessage()));
}
if (!(result instanceof Map)) {
return RespBodyVo.fail("get_form_state 失败:页面没有返回表单信息");
}
Kv data = new Kv();
data.putAll((Map) result);
data.set("url", safeUrl(inst.page));
data.set("scope", selector == null || selector.isBlank() ? "document" : selector);
return RespBodyVo.ok(data);
}
extract_structured_data
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("extract_structured_data",
(svc, id, a) -> svc.extractStructuredData(id, optStr(a, "query"), optBool(a, "extractLinks")));
展开 extractStructuredData 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo extractStructuredData(Long browserId, String query, boolean extractLinks) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
try {
Object text = inst.page
.evaluate("() => {" + " const c = document.getElementById('playwright-highlight-container');"
+ " const prev = c ? c.style.display : null;" + " if (c) c.style.display = 'none';"
+ " const t = document.body ? document.body.innerText.slice(0, 20000) : '';"
+ " if (c) c.style.display = prev || '';" + " return t; }");
Kv kv = Kv.by("query", query).set("text", text);
if (extractLinks) {
Object links = inst.page.evaluate("() => Array.from(document.querySelectorAll('a[href]'))"
+ ".map(a => ({text: (a.innerText || '').trim().slice(0, 80), href: a.href}))");
kv.set("links", links);
}
return RespBodyVo.ok(kv);
} catch (PlaywrightException e) {
return RespBodyVo.fail("extract_structured_data 失败:" + briefMessage(e.getMessage()));
}
}
get_element_text
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_text", (svc, id, a) -> svc.getElementText(id, reqInt(a, "index")));
展开 getElementText 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementText(Long browserId, int index) {
return read(browserId, index, "get_element_text", "text", (locator) -> locator.innerText());
}
get_element_html
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_html", (svc, id, a) -> svc.getElementHtml(id, reqInt(a, "index")));
展开 getElementHtml 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementHtml(Long browserId, int index) {
return read(browserId, index, "get_element_html", "html", (locator) -> locator.innerHTML());
}
get_element_value
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_value", (svc, id, a) -> svc.getElementValue(id, reqInt(a, "index")));
展开 getElementValue 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementValue(Long browserId, int index) {
return read(browserId, index, "get_element_value", "value", (locator) -> locator.inputValue());
}
get_element_attribute
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_attribute", (svc, id, a) -> svc.getElementAttribute(id, reqInt(a, "index"), reqStr(a, "name")));
展开 getElementAttribute 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementAttribute(Long browserId, int index, String name) {
return read(browserId, index, "get_element_attribute", "value", (locator) -> locator.getAttribute(name));
}
get_element_listeners
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_listeners", (svc, id, a) -> svc.getElementListeners(id, a.getInteger("index"),
optStr(a, "selector"), optStr(a, "frame")));
展开 getElementListeners 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementListeners(Long browserId, Integer index, String selector, String frame) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
if ((selector == null || selector.isBlank()) && index == null) {
return RespBodyVo.fail("get_element_listeners 需要 index 或 selector 之一");
}
Locator locator;
String target;
if (selector != null && !selector.isBlank()) {
try {
locator = locatorIn(inst, frame, selector);
} catch (IllegalArgumentException e) {
return RespBodyVo.fail("get_element_listeners 失败:" + e.getMessage());
}
target = "selector=" + selector + frameSuffix(frame);
} else {
locator = locatorOf(inst, index);
target = "index=" + index;
if (locator == null) {
return RespBodyVo.fail("get_element_listeners 索引越界: " + index + indexHint(inst));
}
}
Kv probe;
Frame probeFrame = null;
String elementScript;
try {
if (locator.count() == 0) {
return RespBodyVo.ok(Kv.by("found", false).set("target", target)
.set("note", "没找到这个元素:选择器/索引可能已经过期,重新 get_browser_state 再试"));
}
// CDP 的权威探测需要 frame 与本元素的解析表达式;拿不到就退回启发式,并把结论标成「未知」
if (selector != null && !selector.isBlank()) {
probeFrame = frame == null || frame.isBlank() ? inst.page.mainFrame() : frameOf(inst, frame);
} else {
probeFrame = frameForIndex(inst, inst.domState, index);
if (probeFrame == null) {
probeFrame = inst.page.mainFrame();
}
}
elementScript = elementResolveScript(inst, index, selector);
probe = ListenerProbe.probe(locator, probeFrame, elementScript);
} catch (IllegalArgumentException e) {
return RespBodyVo.fail("get_element_listeners 失败:" + e.getMessage());
} catch (PlaywrightException e) {
return RespBodyVo.fail("get_element_listeners 失败:" + briefMessage(e.getMessage()));
}
if (!Boolean.TRUE.equals(probe.getBoolean("found"))) {
return RespBodyVo.ok(Kv.by("found", false).set("target", target)
.set("note", "没找到这个元素:选择器/索引可能已经过期,重新 get_browser_state 再试"));
}
Kv data = Kv.by("found", true).set("target", target).set(probe);
String note = ListenerProbe.note(probe);
if (note != null) {
data.set("note", note);
}
return RespBodyVo.ok(data);
}
get_element_count
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_count", (svc, id, a) -> svc.getElementCount(id, reqStr(a, "selector"), optStr(a, "frame")));
展开 getElementCount 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementCount(Long browserId, String selector, String frame) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
try {
return RespBodyVo.ok(Kv.by("count", frameOf(inst, frame).locator(selector).count()));
} catch (IllegalArgumentException e) {
return RespBodyVo.fail("get_element_count 失败:" + e.getMessage());
} catch (PlaywrightException e) {
return RespBodyVo.fail("get_element_count 失败:" + briefMessage(e.getMessage()));
}
}
get_element_box
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("get_element_box", (svc, id, a) -> svc.getElementBox(id, reqInt(a, "index")));
展开 getElementBox 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo getElementBox(Long browserId, int index) {
BrowserInstance inst = INSTANCES.get(browserId);
if (inst == null) {
return notFound(browserId);
}
Locator locator = locatorOf(inst, index);
if (locator == null) {
return RespBodyVo.fail("get_element_box 索引越界: " + index + indexHint(inst));
}
try {
BoundingBox box = locator.boundingBox();
if (box == null) {
return RespBodyVo.fail("get_element_box 失败:元素不可见或没有布局信息");
}
return RespBodyVo.ok(Kv.by("x", box.x).set("y", box.y).set("width", box.width).set("height", box.height));
} catch (PlaywrightException e) {
return RespBodyVo.fail(actionFailure("get_element_box", e));
}
}
is_visible
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("is_visible", (svc, id, a) -> svc.isVisible(id, reqInt(a, "index")));
展开 isVisible 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo isVisible(Long browserId, int index) {
return read(browserId, index, "is_visible", "visible", (locator) -> locator.isVisible());
}
is_enabled
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("is_enabled", (svc, id, a) -> svc.isEnabled(id, reqInt(a, "index")));
展开 isEnabled 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo isEnabled(Long browserId, int index) {
return read(browserId, index, "is_enabled", "enabled", (locator) -> locator.isEnabled());
}
is_checked
展开参数注册
源码:playwright-server/src/main/java/nexus/io/ai/browser/actions/registry/CommandTable.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
put("is_checked", (svc, id, a) -> svc.isChecked(id, reqInt(a, "index")));
展开 isChecked 实现
源码:playwright-server/src/main/java/nexus/io/ai/browser/service/PlaywrightService.java。以下为当前实现,可放回原类中阅读;依赖同类字段和辅助方法,并非独立编译单元。
public RespBodyVo isChecked(Long browserId, int index) {
return read(browserId, index, "is_checked", "checked", (locator) -> locator.isChecked());
}
