<!-- Source: https://deepseek-browser-use.io.nexus/03 -->

# 第一个任务：打开页面、读取结果与关闭

本章使用项目自带 `dsb` 客户端完成一个只读任务。先按 [上一章](<https://deepseek-browser-use.io.nexus/02>) 启动服务，再在仓库根目录运行命令。

## 1. 创建任务

```shell
dsb --id 1001 start
```

`1001` 是教学 ID，执行前应确认没有同名任务。实际项目可省略 ID，由服务生成；读取返回的 `data.id`，后续请求始终使用这个值。Java 侧需要生成业务 ID 时使用 `nexus.io.tio.utils.snowflake.SnowflakeIdUtils.id()`。

`start` 默认显示浏览器窗口，便于直接观察执行过程；旧命令的 `--headful` 保留兼容。需要无头模式时显式传 `--headless`，两个开关不能同时使用。协议 `start`（包括批量中的 `start`）省略 `headless` 或传 `false` 均显示窗口，传 `true` 才无头。检查 `data.browser.headless` 和 `data.engineHonored`，确认实际模式与浏览器选择符合预期。

## 2. 导航到示例页面

```shell
dsb --id 1001 run go_to_url -p url=https://example.com --wait-until domcontentloaded
dsb --id 1001 state --full
```

阅读回执里的标题、URL、页签和 `data.text`。成功的导航不一定意味着页面内容加载完整；遇到动态页面，应按需要等待可观察的元素或状态。

导航支持 `--wait-until commit|domcontentloaded|load|networkidle`，默认 `domcontentloaded`。这些阶段不替代业务结果确认。

`state` 默认不画高亮、不截图，索引仍生成。每次读取前会清除旧标记和高亮监听器。需要时分别使用 `state --highlight`、`state --screenshot`，可组合使用。

## 3. 读取正文

```shell
dsb --id 1001 run extract_structured_data -p extractLinks=true
```

检查 `data.text` 是否包含页面正文，并查看 `data.links`。该命令读取当前主文档的文本和链接；更完整的能力边界见 [正文提取](<https://deepseek-browser-use.io.nexus/17>)。

如果只需要标题：

```shell
dsb --id 1001 run get_title
```

## 4. 理解元素索引

先看 [从截图到结构化文本](<https://deepseek-browser-use.io.nexus/01>)：其中保留了原教程的百度高亮截图，并逐项解释编号、缩进、标签和属性。

页面状态可能出现类似下面的行，具体编号以当次结果为准：

```text
[3]<a >更多信息/>
```

数字表示本次快照中的元素索引。确认当前页面确实出现目标元素后，才将实际索引传给 `click_element_by_index`。不要直接复制示例编号去操作另一页面。导航、弹窗、翻页或前端重新渲染后，要重新读取状态。

还应检查 `data.indicesUsable` 和 `data.snapshotConsistent`。页面在采集过程中变化时，服务可能返回 `ok:true`，但将 `indicesUsable` 标成 false；此时不能继续按该快照的索引操作，应等待目标内容稳定后重取状态。

## 5. 关闭本任务

```shell
dsb --id 1001 close
```

仅结束自己的任务。最后一个任务的浏览器与数据页保留给用户，旧任务的监听与路由解除；新任务复用浏览器并另开页签，不接管保留页。

确需关闭时显式执行 `dsb --id 1001 close --close-browser`；即使该任务已结束也可关闭闲置浏览器，有其他活动任务时会拒绝。`shutdown`、`server stop` 会关闭浏览器，不用于普通任务收尾。

## 对应的 HTTP 请求

客户端会把命令转换成统一 JSON。以导航为例：

```json
{
  "id": 1001,
  "method": "go_to_url",
  "params": {"url": "https://example.com"}
}
```

发送到 `POST http://localhost:10049/playwright/command`，请求头为 `Content-Type: application/json`。所有浏览器控制命令都走这个入口，不根据命令名拼接不同 HTTP 路径。

## 如何判断成功

- 检查 HTTP 是否可达，再检查响应 `ok`；HTTP 200 不保证动作成功。
- 读取命令结果，确认当前 URL、文本或字段值符合目标。
- 对会改变页面的动作，结合截图与动作后的页面观察判断。
- CLI 退出码 0 表示成功，1 表示传输或协议问题，2 表示业务失败，3 表示调用用法错误。

下一步：[客户端用法与实现](<https://deepseek-browser-use.io.nexus/03_client>)，然后阅读[统一请求与响应协议](<https://deepseek-browser-use.io.nexus/04>)。
