Metadata-Version: 2.3
Name: ksen-ziniao
Version: 0.1.52
Summary: Add your description here
Author: yongg
Author-email: yongg <2814744065@qq.com>
Requires-Dist: drissionpage>=4.1.1.4
Requires-Dist: ksen-hyperv>=0.1.1
Requires-Dist: paramiko>=4.0.0
Requires-Dist: requests>=2.34.2
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# ksen-ziniao

`ksen-ziniao` 是一个用于管理紫鸟浏览器店铺环境的 Python 库。它将紫鸟客户端和
DrissionPage 串联起来，可选择直接连接已有主机或自动启动 Hyper-V 虚拟机，按
店铺名打开浏览器环境，并返回可直接操作的 Chromium 页面对象。

## 功能特性

- 自动启动 Hyper-V 虚拟机并等待其进入 `Running` 状态
- 自动获取虚拟机 IP 并连接紫鸟客户端
- 按店铺名称查找、启动和关闭紫鸟浏览器环境
- 返回 DrissionPage 的 `ChromiumPage` / `Chromium` 对象
- 使用 SQLite 缓存店铺的 Chrome 调试端口
- 缓存端口失效时自动重新启动店铺，最多重试 3 次
- 支持并发启动多个店铺环境
- 支持不管理虚拟机、直接连接已有 Windows 紫鸟主机
- 支持在 Ubuntu 通过 SSH 密码认证调用远端 Bash，无需部署 8000 端口命令代理
- 提供上下文管理器，安全释放 WMI/COM 和 SQLite 资源

## 运行要求

- Python 3.12 或更高版本
- 已安装并可正常登录的紫鸟浏览器客户端
- 直连和 Hyper-V 模式的紫鸟目标主机为 Windows
- Hyper-V 模式还要求控制端为 Windows、已启用 Hyper-V，且当前进程具备管理
  虚拟机所需权限
- 目标主机网络可达，并能访问以下端口：
  - `8000`：远程命令执行服务
  - `16851`：紫鸟客户端 HTTP 通信端口，支持在构造时修改
  - 店铺启动后返回的 Chrome DevTools 调试端口

> `ZiniaoBrowserV2` 会通过 `http://<host>:8000/execute` 启停
> `SuperBrowser.exe`。使用 Hyper-V 模式前，请确保虚拟机内已运行兼容的命令执行
> 服务，并允许对应端口通过防火墙。

使用 `ZiniaoBrowserUbuntu` 控制远端 Ubuntu 时不需要 8000 端口服务，但需要：

- Python 控制端能访问远端 SSH 端口（默认 `22`）；
- 远端 SSH 账号允许密码认证；
- 远端 Ubuntu 已安装 OpenSSH Server、Bash 和 coreutils；
- SSH 登录用户已有活动的图形桌面会话（支持 GNOME、KDE、XFCE、Cinnamon）；
- 远端 SSH 主机密钥已存在于 Ubuntu 用户的 `known_hosts`，或者首次连接时显式
  设置 `ssh_auto_add_host_key=True`。

## 安装

使用 uv 安装项目依赖：

```powershell
git clone <repository-url>
cd ksen_ziniao
uv sync
```

作为依赖安装时：

```powershell
uv add ksen-ziniao
```

也可以使用 pip 从本地源码安装：

```powershell
python -m pip install .
```

## 快速开始

### Hyper-V 模式

这是项目的主要入口。首次调用 `get_env()` 时，服务会按以下顺序完成初始化：

1. 启动指定的 Hyper-V 虚拟机；
2. 等待虚拟机进入 `Running` 状态并获取 IP；
3. 启动或连接紫鸟客户端；
4. 查找并打开指定店铺；
5. 缓存调试端口并返回 `ChromiumPage`。

```python
import logging

from ksen_ziniao import ZbCredential, ZiniaoBrowserHyperV

logging.basicConfig(level=logging.INFO)

credential = ZbCredential(
    company="你的公司名称",
    username="你的紫鸟用户名",
    password="你的紫鸟密码",
)

with ZiniaoBrowserHyperV(
    vm_name="ziniao-vm",
    zb_path=r"C:\Users\xen\SuperBrowser\SuperBrowser.exe",
    zb_credential=credential,
    kv_db_path=r"C:\ksen-data\ziniao-ports.db",
) as service:
    page = service.get_env("店铺名称")
    page.get("https://example.com")
    print(page.title)
```

`get_env()` 支持紫鸟客户端提供的店铺名称模糊匹配。建议业务代码中使用唯一且
稳定的店铺名称，避免匹配到非预期店铺。

### 不管理虚拟机，直接获取店铺环境

`ZiniaoBrowserDirect` 提供与 Hyper-V 模式相同的端口缓存、探活、重试和
`get_env()` 接口，但不会启动、停止或探测虚拟机。远程 Windows 主机需要运行
兼容的 PowerShell 命令执行服务。未提供 ``zb_path`` 时，会通过该服务执行
PowerShell，自动查询远程主机注册表并验证紫鸟客户端路径。

```python
from ksen_ziniao import ZbCredential, ZiniaoBrowserDirect

credential = ZbCredential("你的公司名称", "你的紫鸟用户名", "你的紫鸟密码")

with ZiniaoBrowserDirect(
    host="127.0.0.1",
    zb_credential=credential,
    kv_db_path=r"C:\ksen-data\ziniao-direct-ports.db",
    pwsh_proxy_port=8000,  # PowerShell 命令代理端口，可按服务配置修改。
    # 本机可省略 zb_path，由 Windows 注册表自动发现。
) as service:
    page = service.get_env("店铺名称")
    page.get("https://example.com")
```

### 直接连接紫鸟客户端

不需要管理 Hyper-V 时，可直接使用 `ZiniaoBrowserV2`。`host` 可以是本机地址，
也可以是已运行紫鸟客户端及远程命令服务的 Windows 主机地址。

```python
from ksen_ziniao import ZiniaoBrowserV2

browser_service = ZiniaoBrowserV2(
    company="你的公司名称",
    username="你的紫鸟用户名",
    password="你的紫鸟密码",
    client_path="/opt/ziniao/ziniaobrowser",
    host="127.0.0.1",
    socket_port=16851,
)

browser, debugging_port = browser_service.open_store_by_name(
    "店铺名称",
    check_ip=True,
    open_launcher=True,
)

if browser is None:
    raise RuntimeError("店铺环境启动失败")

tab = browser.latest_tab
tab.get("https://example.com")

browser_service.close_store_by_name("店铺名称")
```

### Ubuntu 通过 SSH 控制远端紫鸟客户端

`ZiniaoBrowserUbuntu` 使用 Paramiko 进行 SSH 密码认证，直接在远端执行 Bash
命令，取代原先的 8000 端口命令代理。SSH 密码不会出现在进程命令行中，远端
不需要安装 PowerShell。

```python
from ksen_ziniao import ZiniaoBrowserUbuntu

browser_service = ZiniaoBrowserUbuntu(
    company="你的公司名称",
    username="你的紫鸟用户名",
    password="你的紫鸟密码",
    client_path="/opt/ziniao/ziniaobrowser",
    host="192.168.1.20",
    ssh_username="xen",
    ssh_password="远端 SSH 密码",
    ssh_port=22,
    socket_port=18888,
    # 仅适合首次受信网络接入；生产环境建议预先维护 known_hosts。
    ssh_auto_add_host_key=True,
)

try:
    browser, debugging_port = browser_service.open_store_by_name("店铺名称")
finally:
    browser_service.close()
```

`send_cmd(command, timeout=60)` 的返回结构与旧 HTTP 命令代理一致：
`{"return_code": int, "stdout": str, "stderr": str}`。

启动 WebDriver 时会优先查找当前 SSH 用户的桌面 `ziniaobrowser` 进程；若紫鸟
尚未启动，则回退到 `gnome-shell`、`gnome-session-binary`、`plasmashell`、
`xfce4-session`、`cinnamon` 或 `Xwayland`。程序从 `/proc/<pid>/environ`
继承 `DISPLAY`、`XAUTHORITY`、`WAYLAND_DISPLAY`、
`DBUS_SESSION_BUS_ADDRESS` 和 `XDG_RUNTIME_DIR`，随后使用 `nohup` 启动独立
WebDriver 进程。启动日志写入 `~/ziniao-web-driver.log`，指定端口真正监听后
`_start_browser()` 才会返回成功。初始化时只终止旧 WebDriver 实例，不会关闭
用于提供桌面会话环境的紫鸟主进程。

在 Ubuntu 24.04 Wayland 环境下，如果桌面进程的 `/proc/<pid>/environ` 未包含
图形变量，程序还会从 `systemctl --user show-environment` 自动补齐。
店铺内核的 CDP 调试端口通常只监听远端 `127.0.0.1`；`get_browser()` 会自动
创建本机随机端口到远端 CDP 端口的 SSH 隧道，无需开放额外防火墙端口。

## 核心 API

### `ZbCredential`

紫鸟登录凭据数据类，包含 `company`、`username` 和 `password`。

### `ZiniaoBrowserHyperV`

| 参数 | 类型 | 说明 |
| --- | --- | --- |
| `vm_name` | `str` | Hyper-V 虚拟机名称 |
| `zb_path` | `str` | 虚拟机内 `SuperBrowser.exe` 的完整路径 |
| `zb_credential` | `ZbCredential` | 紫鸟登录凭据 |
| `kv_db_path` | `str \| Path` | SQLite 端口缓存文件；测试时可传 `:memory:` |
| `socket_port` | `int` | 紫鸟客户端通信端口，默认 `16851` |

主要方法：

- `get_env(ziniao_name)`：获取指定店铺的 `ChromiumPage`
- `close()`：释放 Hyper-V/WMI COM 对象并关闭 SQLite 连接

### `ZiniaoBrowserV2`

主要方法：

- `get_browser_list()`：获取店铺列表
- `get_store_by_name(store_name)`：按名称查找店铺
- `open_store_by_name(store_name, check_ip=True, open_launcher=True)`：打开店铺
- `close_store_by_name(store_name)`：关闭店铺
- `delete_all_cache(cache_path=None)`：删除紫鸟客户端缓存
- `exit_client()`：退出紫鸟客户端

### `ZiniaoBrowserDirect`

不管理虚拟机的高层环境服务。构造参数为 `host`、`zb_credential`、
`kv_db_path`、可选的 `zb_path` 和 `socket_port`；主要方法为：

- `get_env(ziniao_name)`：复用缓存端口或启动店铺，并返回 `ChromiumPage`
- `close()`：关闭 SQLite 资源，不退出共享的紫鸟客户端

### `ZiniaoBrowserUbuntu`

继承 `ZiniaoBrowserV2` 的店铺管理和 CDP 操作能力，并用 SSH + Bash 覆盖
`send_cmd()`。构造时必须提供 `ssh_username` 和 `ssh_password`；默认校验 SSH
主机密钥，不会自动信任未知主机。店铺 CDP 连接自动通过同一个 SSH 会话转发。

## 端口缓存

Hyper-V 模式会将调试端口以 `<店铺名称>_port` 为键写入 SQLite。再次获取同一
店铺时，会先访问 `http://<虚拟机IP>:<端口>/json/version` 检查端口是否有效；
端口不可用时将重新打开店铺并更新缓存。

若仅使用 `KVStore`，数据库路径的解析优先级为：

1. 构造函数显式传入的路径；
2. 环境变量 `KSEN_ZINIAO_KV_DB`；
3. 默认路径 `~/.ksen_ziniao/kv.db`。

## 开发与测试

安装开发依赖并运行测试：

```powershell
uv sync --dev
uv run pytest
```

测试使用 Mock 和内存 SQLite 隔离真实的 Hyper-V、紫鸟客户端及网络环境，不会
主动启动真实虚拟机或店铺。

## 注意事项

- Hyper-V 管理依赖 Windows WMI/COM，请在创建服务的同一线程中使用并关闭服务。
- 推荐使用 `with ZiniaoBrowserHyperV(...) as service`，确保 COM 和数据库连接按
  正确顺序释放。
- 紫鸟账号密码属于敏感信息，请从环境变量或安全配置中心读取，不要提交到仓库。
- `kv_db_path` 的父目录不存在时会自动创建。
- 初始化可能需要下载或更新浏览器内核，首次运行耗时通常更长。
