Files
StudioLift/skills/yt-studio-groupid-lookup/SKILL.md

125 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: "yt-studio-groupid-lookup"
description: "把一批群组名批量解析为 entity_id即 groupId并标注其归属的内容所有者。围绕 scripts/lookup_groups.py用「套件回放」search_groups 接口:在线捕获鉴权套件后并发查询,或离线用已存套件回放。当用户给出群组名清单、要查找/映射/匹配群组的 groupId 或 entity_id、确认某群组属于哪个所有者/内容管理器、排查群组 ID 查不到或回放 401 时使用。"
---
# 群组名解析为 entity_id脚本版
把群组名 --> `groupId`(即 explore URL 里的 `entity_id`),并标注归属的内容所有者。底层执行 `scripts/lookup_groups.py`。核心是「套件回放」:**套件**(捕获页面的完整鉴权头 + 请求体模板),**回放**(重发 `search_groups`,只改 `query`),因手写请求必 401。
## 何时使用
- **批量解析**:用户有一批群组名,要拿到每个名字对应的 groupId / entity_id。
- **归属确认**同名群组可能多个所有者都有需要确认某群组属于哪个内容管理器ownerId + 显示名)。
- **建 URL 前置**:要生成 explore 报告 URL但清单里只有群组名、没有 entity_id。
- **排查失败**:回放遇到 401 / 查不到 / 大小写差异,需要定位修复。
## 领域词汇
- **套件Bundle**:从页面捕获的一次 `search_groups` 请求 = 完整请求头(`Authorization: SAPISIDHASH...``Cookie``X-YouTube-Delegation-Context` 等)+ 请求体模板(含 `context.user.delegationContext`)。一个内容所有者一份。手写必 401唯一可靠来源。
- **回放Replay**:用套件重发 `search_groups`**只改 body 的 `query` 字段**,其余(尤其 delegation 语境)一律不动。
- **实体ID / groupId**:响应 `groupDatas[].groupId`,即 explore URL 的 `entity_id`(如 `NCy9C2QPQ1E`)。
- **精确命中**:响应当中存在 `displayName === 查询名` 的项,直接取它的 groupId命中即停不再往下查。
- **变体候选**:无精确命中时,接口仍可能返回前 5 个相近名,写入结果「备注」列供人工复核。
## 脚本与依赖
- 脚本:`scripts/lookup_groups.py`(本技能目录下;若缺失,用 SearchCodebase 按 `lookup_groups.py` 定位)。
- 依赖playwright、requests、openpyxl 已统一在根 `pyproject.toml` 声明(`uv sync` 自动装),环境准备见 `uv-env-setup` 技能。
- 登录态必须已存在:脚本不登录,只复用已登录 YouTube Studio 会话,否则跳 Google 登录页。
## 选择运行分支
| 你的情况 | 分支 | 关键参数 |
|---|---|---|
| 要在线拿新套件并立即查询 | 分支 A捕获+回放 | `--url` + `--names` |
| 套件已存盘(`--save-bundles` 产物) | 分支 B离线回放 | `--bundles` + `--names` |
| 只想捕获/校验套件,先不查 | 分支 C仅捕获 | `--url`(不带 `--names` |
| 无浏览器/网络,验脚本逻辑 | 分支 D自测 | `--selftest` |
多所有者的分三种做法(三者都对应分支 A`--url` 重复传多次、或 `--url ... --save-bundles bundles.json` 先存盘、或下次直接用 `--bundles bundles.json`(分支 B
## 工作流
### 步骤 0环境与自测分支 D
```bash
uv run python scripts\lookup_groups.py --selftest
```
**完成判据**:打印 `selftest OK`,退出码 0无需浏览器/网络)。
### 步骤 1确认登录态来源
复用已登录 YouTube Studio 的浏览器会话,否则跳 Google 登录页。与 `youtube-studio-csv-download` 同一套约定:
- 方式 A能关浏览器`--user-data-dir <目录> --channel chrome|msedge`,二者必须同品牌。
- 方式 B浏览器不能关`chrome.exe --remote-debugging-port=9222``msedge.exe --remote-debugging-port=9222`,再加 `--connect http://localhost:9222`
**完成判据**:得到任意一种可复用的登录态(用户数据目录路径,或调试端口号)。
### 步骤 2拿到所有者 URL 与群组名单
- 所有者 URL`studio.youtube.com/owner/<ownerId>/analytics?...`;脚本自动从 URL 路径 `owner/<id>``?o=<id>` 提取 ownerId不需手工填。
- 群组名单json / txt / csv / xlsx 均可,支持 `群组名称``group_name``实体名称``名称` 等列名,自动去重。(格式细节见 [references/input-guide.md](references/input-guide.md)
**完成判据**`--names` 指向的文件能被脚本解析出非空名单(列名可识别)。
### 步骤 3运行脚本
分支 A在线捕获 + 回放):
```powershell
# 单所有者
uv run python scripts\lookup_groups.py --url "<owner URL>" --names 名单.xlsx --channel chrome --user-data-dir "$env:LOCALAPPDATA\Google\Chrome\User Data"
# 多所有者:--url 重复;浏览器不能关就改用 --connect
uv run python scripts\lookup_groups.py --url "<owner1 URL>" --url "<owner2 URL>" --names 名单.csv --connect http://localhost:9222 --save-bundles bundles.json
```
分支 B离线回放套件已存盘无需浏览器
```powershell
uv run python scripts\lookup_groups.py --bundles bundles.json --names 名单.json --out result.xlsx
```
分支 C仅捕获/校验套件,暂不查询):
```powershell
uv run python scripts\lookup_groups.py --url "<owner URL>" --save-bundles bundles.json
```
**关键行为**
- 打开页面后先**自动触发一次群组搜索**(猜搜索框);猜不中会提示「在浏览器顶部搜索框输入任意词并回车」,只需触发一次 `search_groups` 请求即可。
- 捕到请求后,脚本校验 `delegationContext.externalOwnerId` 与 URL ownerId 是否一致、鉴权头是否齐全(缺 Authorization/Cookie/delegation 是 401 根因,会在捕获时直接打警告)。
- 回放用线程本地 Session并发默认 8 线程)逐个名字 × 逐个所有者,**首个精确命中即停**。
**完成判据**:终端打印 `[输出] 精确命中 N/M -> <路径>`,退出码 0且生成结果文件。
### 步骤 4校验产物与处理未命中
- 结果列:`group_name / ownerid / owner_display / groupid / 备注``ownerid + owner_display` 标注群组归属的所有者。
- 未命中的名字会列在末尾 `[复核] 未命中 N 个`,其候选/线索在「备注」列。
- 处理变体:若备注里只有大小写/空格差异的候选,直接改用候选 groupId若跨所有者都命中以**精确 displayName** 为准核对归属;若名字疑似错字,用更短关键词(如品牌名)重跑一次。
**完成判据**:无 `HTTPxxx` / `ERR` 残留;每个群组要么有确定 groupId要么在备注列明确记录了候选或原因。
## 常用参数速查
| 参数 | 说明 |
|---|---|
| `--url` | 所有者分析页 URL可重复多所有者 |
| `--names` | 群组名单json / txt / csv / xlsx |
| `--bundles` | 已有套件 json离线回放或与 `--url` 捕获结果合并) |
| `--save-bundles` | 把套件写盘,供下次离线回放 |
| `--out` | 结果文件,默认 `group_entity_id_result.xlsx`,缺 openpyxl 自动回退 csv |
| `--max-workers` | 并发线程数,默认 8 |
| `--connect` | CDP 附加到已打开浏览器 |
| `--user-data-dir` / `--channel` | 用已登录用户数据目录启动 |
| `--owner-display` | 所有者显示名(可选,单 `--url` 时用于结果标注) |
| `--wait-seconds` | 等待手动触发搜索的最长秒数,默认 180 |
## 参考
- [名单与套件制作指南](references/input-guide.md):名单文件格式/列别名、套件 bundles.json 结构、多所有者、产物核对。
- [常见问题排查](references/troubleshooting.md):按 现象 → 原因 → 解决 逐条排查401、未登录跳转、捕获不到请求、查不到、CDP 连不上、channel 不匹配等)。