---
name: dp-browser
description: 用 DrissionPage 控制常驻浏览器(默认端口 9333)的快捷接口:打开/切换标签页、点击、输入、下拉选择、按键、滚动、执行 JS、截图,以及只含人类可见元素(链接/按钮/输入框/下拉/文本/标题/图片,不含 CSS/JS 内部信息)的页面快照 snapshot / snapshot -i。浏览器进程在命令之间保持运行,标签页、登录态、页面状态跨命令持续存在。Use for browsing web pages, clicking links/buttons, filling forms, extracting human-visible page content, and any persistent browser automation task.
---

# dp-browser — DrissionPage 常驻浏览器

用 DrissionPage 控制一个**常驻** Chrome 浏览器。每次调用脚本都连接同一个浏览器
(默认端口 `9333`),脚本结束后浏览器**不会关闭** —— 标签页、登录态、页面滚动状态
在多次调用之间持续存在。手动操作浏览器窗口也会同步生效。

> 原理:`from DrissionPage import Chromium; tab = Chromium(9333).latest_tab`
> DrissionPage 会自动启动(或连接)浏览器,退出脚本不销毁浏览器。
> 语法遵循官方文档示例(4.x 最新版):`Chromium().latest_tab` → `tab.get(url)` →
> `tab.ele('#id')` / `tab.ele('@value=登 录')` → `ele.input()` → `ele.click()`
> (见 https://www.drissionpage.cn/get_start/examples/control_browser );
> 本技能用 `Chromium(9333)` 固定调试端口,保证多次调用连到同一个浏览器。

## 何时使用

- 需要打开网页、点击链接/按钮、填写表单、下拉选择、勾选复选框
- 需要读取页面**人类可见**的内容(不需要 CSS/JS/源码内部信息)
- 需要跨多条命令保持浏览器状态(登录态、标签页、已滚动位置)
- 不适合:需要无头浏览器批量抓取(浏览器是有窗口的常驻实例)

## 用法

所有命令输出 JSON(`{"ok": true/false, ...}`),失败时 exit code 为 1。

```bash
python scripts/dp_browser.py <命令> [参数]
```

> 脚本在本技能目录 `scripts/` 下。pi 安装后技能目录位于
> `~/.pi/agent/skills/dp-browser/`(全局)或项目 `.pi/skills/dp-browser/`(项目本地);
> 仓库内则先 `cd skills/dp-browser` 再运行。

若当前 Python 没有 DrissionPage,脚本会自动在技能目录创建 `.venv-dp` 并安装
(首次约 30 秒,需联网);项目里已有带 DrissionPage 的 venv(如 `.venv`)会优先复用。
也可以手动 `pip install drissionpage`。

## 命令速查

| 命令 | 说明 |
|---|---|
| `open <url>` | 当前标签页打开网址(无标签页则新建;自动补 `https://`) |
| `new <url>` | 新标签页打开 |
| `tabs` | 列出所有标签页 |
| `switch <序号\|id\|网址/标题片段>` | 切换标签页 |
| `close [序号]` | 关闭标签页(默认当前) |
| `url` / `title` | 当前标签页网址和标题 |
| `back` / `forward` / `refresh` | 后退 / 前进 / 刷新 |
| `wait <秒>` | 等待 |
| `snapshot` | 页面可见内容快照(见下) |
| `snapshot -i` | 仅交互元素快照 |
| `click <定位\|序号>` | 点击(`--js` 强制 JS 点击) |
| `input <定位> <文本>` | 输入(先清空) |
| `select <定位> <选项>` | 下拉选择(文本/值,数字按序号) |
| `check <定位>` / `uncheck <定位>` | 勾选 / 取消勾选 |
| `type <文本>` | 向当前焦点元素输入文本 |
| `press <键\|组合>` | 按键,如 `Enter`、`Escape`、`ctrl+a`、`shift+Tab` |
| `hover <定位>` | 悬停 |
| `scroll top\|bottom\|up\|down [px]\|to <y>\|<px>` | 滚动 |
| `wait_ele <定位> [秒]` | 等待元素出现(默认 10 秒) |
| `js <代码>` | 执行 JS(函数体形式,可用 `return`) |
| `jsx <表达式>` | 执行 JS 表达式,如 `document.title` |
| `screenshot [路径] [--full]` | 截图(PNG) |
| `quit` | 关闭浏览器,结束会话 |
| `help` | 帮助 |

## 定位规则

- 带前缀直接透传:`css:...`、`xpath:...`(或 `x:`)、`text:...`(或 `t:`,包含匹配取第一个)、`@属性=值`、`tag:...`
- 裸 `#id` `.class` `[attr]` 或标签名(如 `button`)→ 当作 css
- 其它裸文本(如 `Sign in`)→ 当作 `text:` 包含匹配
- 数字 → 当作 `snapshot -i` 里元素的序号(点击时重新采集,页面若变化序号可能漂移)

## snapshot 说明

只返回**人类可见**元素,不包含 CSS/JS/样式/源码内部信息(隐藏元素 `display:none`、
不可见、`aria-hidden`、宽高 ≤1px 均被过滤;密码值打码)。

`snapshot -i` 返回:页面信息 + 交互元素数组,每个元素含:

```
i           序号(1 起,可用来 click N)
tag         标签(a / button / input / select / textarea / summary / details ...)
text        可见文本(截断 200 字)
href        链接绝对地址(a 元素)
role / aria / title / id / name / type / placeholder
value       输入框当前值(密码打码;截断 60 字)
checked     复选框/单选钮状态
disabled    是否禁用
label       关联 label 文本(表单控件)
```

`snapshot`(不带 `-i`)额外返回 `headings`(h1-h6 带层级)、`paragraphs`(正文/列表项/
引用/代码块)、`images`(src/alt/尺寸)、`iframes`(仅 src/title,内部内容需用 `js` 处理)。

典型流程:

```bash
python .../dp_browser.py open https://example.com
python .../dp_browser.py snapshot -i        # 看有哪些可交互元素
python .../dp_browser.py click 3            # 或 click 'text:Sign in'
python .../dp_browser.py input 'css:#q' 关键词
python .../dp_browser.py press Enter        # 提交
python .../dp_browser.py snapshot           # 读结果页可见内容
```

## 常驻浏览器说明

- 第一次 `open` 自动启动 Chrome 并保持;之后的每条命令秒级连接
- `latest_tab` 是最近激活的标签页 —— 手动点浏览器窗口切换标签页,后续命令跟随
- 结束会话用 `quit`(真正关闭浏览器);之后 `open` 会重新启动
- 本技能的命令脚本见 `scripts/dp_browser.py`,命令全集可运行 `help` 查看

## 常见问题

- **连接失败 / 端口被占用**:本机 Chrome 若以普通模式运行(无调试端口),新启动的
  实例无法带上调试端口,会连不上。先完全退出 Chrome 再试;或设置
  `DP_USER_DATA` 指向独立用户目录(用独立配置启动,与日常 Chrome 互不干扰)。
- **换端口**:设置环境变量 `DP_BROWSER_PORT`(默认 9333),或 `--port <端口>`。
- **元素找不到**:先 `snapshot -i` 看当前可见元素;动态加载内容先 `wait_ele` 或 `wait`。
- **iframe 内部内容**:`snapshot` 只列出 iframe 本身;内部元素用 `js` 命令直接操作。
- **浏览器被手动关闭了**:下一次命令会自动重新启动浏览器(新会话,登录态可能丢失)。
