7.9 KiB
7.9 KiB
name, description
| name | description |
|---|---|
| yt-studio-groupid-lookup | 把一批群组名批量解析为 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)
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)
完成判据:--names 指向的文件能被脚本解析出非空名单(列名可识别)。
步骤 3:运行脚本
分支 A(在线捕获 + 回放):
# 单所有者
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(离线回放,套件已存盘,无需浏览器):
uv run python scripts\lookup_groups.py --bundles bundles.json --names 名单.json --out result.xlsx
分支 C(仅捕获/校验套件,暂不查询):
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 |