Files
StudioLift/assets/skill-问题复盘与优化建议.md
Sidney Zhang 9020752eed feat(scripts): 添加 PEP 723 脚本元数据并修复 HTTP/2 伪头过滤问题
- 为 build_studio_urls.py 和 lookup_groups.py 添加 PEP 723 依赖声明
- 修复 HTTP/2 伪头导致 requests 抛 InvalidHeader 的问题
- 添加 CDP 端口连通性预检查及启动指引
2026-08-27 13:33:34 +08:00

11 KiB
Raw Permalink Blame History

StudioSkillsSet 四技能使用问题复盘与优化建议

记录日期2026-08-26 涉及技能:uv-env-setupyt-studio-groupid-lookupyt-studio-url-builderyoutube-studio-csv-download 数据链路:群组名 →(groupid-lookup)→ groupId →(url-builder)→ explore URL →(csv-download)→ CSV zip


一、结论速览

技能 是否遇到问题 问题是否已解决 是否需要优化 优化紧急度
uv-env-setup 是(命令不可用) 是(轻)
yt-studio-groupid-lookup 是(端口/登录/401/伪头)
yt-studio-url-builder 否(但存在隐性前置依赖) 是(轻)
youtube-studio-csv-download 是(登录/按钮定位/base64 解码)

整体结论4 个技能功能均跑通最终产物6 份 CSV zip全部有效。其中 youtube-studio-csv-download 暴露了 2 处真实脚本缺陷(导出按钮定位、zippedData 解码),是本次最需要回填到技能脚本的修复点。


二、uv-env-setup环境准备

问题 1uv 命令不被识别

  • 现象:执行 uv --versionuv syncThe term 'uv' is not recognized
  • 为什么会出现uv 刚安装,当前 PowerShell 会话的 PATH 未刷新;或者安装方式(如 pip install uv)没有把可执行文件加入 PATH。
  • 解决方法:改用 python -m uv 调用;或在后续会话中直接调用项目已有的 .venv\Scripts\python.exe 绕过 uv 代理。
  • 如何避免:安装后重开终端;或脚本执行统一改为"优先 .venv\Scripts\python.exe 直调,回退 uv run"。

问题 2已有 .venv 但缺 pyproject.toml

  • 现象:项目已存在 Python 3.12.6 的 .venv(内含 pandas/openpyxl/playwright但没有 pyproject.toml
  • 为什么会出现:原环境是手动 pip install 搭出来的,不是 uv 管理。
  • 解决方法:新建 pyproject.toml 声明依赖作为唯一事实来源,uv sync 复用现有 Python 生成 uv.lock
  • 如何避免:首次迁移到 uv 时先补 pyproject.toml,再 uv sync

是否已解决:是。环境最终就绪,三条自检(import pandas/openpyxl/playwright--selftest--help)通过。


三、yt-studio-groupid-lookup群组名 → groupId

问题 1Chrome 调试端口 9222 连不上

  • 现象--connect http://localhost:9222 连不上,报"无法连接到远程服务器"。
  • 为什么会出现Chrome 未以 --remote-debugging-port=9222 启动。
  • 解决方法:用带调试端口的命令重启 Chrome。
  • 如何避免:运行前先 Invoke-WebRequest http://localhost:9222/json/version 探测端口是否在线。

问题 2Chrome 进程未完全退出,调试端口参数被忽略

  • 现象:已带参数重启 Chrome但 9222 仍不通。
  • 为什么会出现:后台仍有 Chrome 残留进程,新启动实例的 --remote-debugging-port 被已运行实例"吞掉"Chrome 单实例复用机制)。
  • 解决方法:完全退出所有 Chrome 进程后再启动调试实例,或者改用独立 --user-data-dir 隔离启动。
  • 如何避免:启动前检测残留进程;或固定使用独立 profile 目录 + 调试端口。

问题 3回放请求全量 401

  • 现象search_groups 回放返回 HTTP401
  • 为什么会出现:套件过期(鉴权头是逐请求计算的),或捕获时鉴权头不全。
  • 解决方法:重新在线捕获套件,更新 bundles.json
  • 如何避免:套件一次性用完即弃;长期复用前先重新捕获校验。

问题 4HTTP/2 伪头导致 InvalidHeader 报错

  • 现象requestsInvalidHeader: Invalid leading whitespace...
  • 为什么会出现:捕获到的请求头里残留了 HTTP/2 伪头 :authority:method:path:scheme,这些带冒号前缀的伪头不能被 requests 直接作为普通请求头发送。
  • 解决方法:从 bundles.json 中手动删除这 4 个伪头字段。
  • 如何避免:脚本捕获时自动过滤伪头,而不是留到下游报错后人工处理。

是否已解决是。3 个群组名全部解析出 groupId 并标注归属所有者(产物 群组ID结果-需求输入-测试.xlsx)。


四、yt-studio-url-builder生成 explore URL

  • 现象:本身运行无报错,从需求清单成功生成 6 条 URL。
  • 隐性前置依赖(潜在问题)URL 中 entity_id 必须是群组的 groupId清单里只有群组名、没有 ID 时会缺 entity_id 而失败。本次实际流程正是"先 groupid-lookup 填 ID再 url-builder 生成 URL"。
  • 如何避免:在 SKILL.md 中显式注明"清单若只有群组名,需先经 groupid-lookup 补 entity_id"。

是否已解决:是。产物 studio_urls_需求输入-测试.csv 含 6 条有效 URL。


五、youtube-studio-csv-download下载 CSV

这是问题最集中的技能,存在 2 处需要回填的脚本缺陷。

问题 1登录态失效跳转 Google 登录页

  • 现象:用已保存的 cdp-profileChromeedge-yts-debug-profileEdge启动页面都停在 accounts.google.com 登录页。
  • 为什么会出现:两个 profile 里保存的 YouTube Studio 登录会话已过期。注意Edge 配置目录的 Cookies 文件里仍能看到 SAPISID/SID/__Secure-3PSID 等 cookiecookie 存在不等于会话仍有效Google 仍要求重新登录。
  • 解决方法:由用户在浏览器中手动完成一次登录,之后复用该已登录会话。
  • 如何避免:下载前先探测页面是否跳登录页(脚本已有该判断,但只在跳转后提示);长期任务建议在开始前确认一遍登录态。

问题 2导出按钮定位失败脚本缺陷 1

  • 现象page.get_by_text("导出当前视图") 点击超时 30s日志 waiting for get_by_text("导出当前视图")
  • 为什么会出现:当前 YouTube Studio「高级模式」页的导出入口是右上角的下载图标按钮,它只有 aria-label="导出当前视图"没有可见文本。脚本用 get_by_text(文本匹配)自然匹配不到。
  • 解决方法:改用 page.get_by_label("导出当前视图")(或 get_by_role("button", name=...)[aria-label=...]),已验证三种方式都能命中 count=1
  • 如何避免:对"图标类按钮"优先用 aria-label 定位,而非可见文本。

问题 3zippedData 解码失败 / 生成的 zip 损坏(脚本缺陷 2核心

  • 现象:拦截到 csv_export 响应后,base64.b64decode(zippedData)Incorrect padding;即使解码未抛错,写出的 zip 文件用 zipfile 打开报 BadZipFile: Bad magic number for central directory(文件尾部无 PK\x05\x06 结束记录)。
  • 为什么会出现:响应中 zippedData 字段是 URL-safe base64(用 -_ 替代 +/)且去掉了 = 填充。脚本用标准 base64.b64decode 解码:遇到 -/_ 或非 4 对齐长度时,要么抛 padding 错,要么静默解出损坏字节流,导致 zip 不完整。
  • 排查过程:诊断脚本发现响应 status=200content-encoding: brBrotli但 Playwright 已自动解压、resp.json() 能正常解析,因此排除了"响应被压缩截断"的猜想,最终锁定是 base64 变体问题。
  • 解决方法:解码前补 = 填充(z += "=" * (-len(z) % 4)),并用 base64.b64decode(z, altchars=b"-_") 指定 URL-safe 字符表。
  • 如何避免:对来自前端接口的 base64 字段,先确认是否为 URL-safe + 无填充变体再解码;解码后增加 zipfile.testzip() 完整性校验。

是否已解决:是。修正后 6/6 条全部下载成功,每个 zip 含 表格数据.csv / 图表数据.csv / 总计.csv,抽查验证美国筛选、按频道明细、按日收益均正确。


六、执行过程与原 skill 的差异对比

环节 原 skill 脚本行为 本次实际执行行为 差异原因 如何回归/解决
csv-download导出按钮 get_by_text("导出当前视图") get_by_label("导出当前视图") 前端已改为图标按钮,无可见文本,原定位失效 回填脚本:优先 get_by_label,可保留 get_by_text 兜底
csv-downloadzip 解码 base64.b64decode(zipped) = 填充 + altchars=b"-_" 接口返回 URL-safe、无填充 base64 回填脚本:改用 URL-safe 解码 + 完整性校验
csv-download下载目录 写死 D:\Downloads --download-dir 指向工作区 YT导出 沙箱外 D:\Downloads 用户不可见 脚本已支持 --download-dir,无需改;仅执行时传参
csv-download批量下载 run() 单 URL、每次新建会话 外层驱动循环复用一次浏览器连接逐条下载 + zip 校验 + 失败重试 清单有 6 条 URL单次调用不够 可选:给脚本增加批量能力;或保持单次语义、由调用方写循环
groupid-lookup伪头 捕获后原样落 bundles.json 人工删除 4 个 HTTP/2 伪头 脚本未在捕获阶段过滤伪头 建议:捕获时自动过滤伪头
url-builder 直接读清单生成 URL 先经 groupid-lookup 补 entity_id 再生成 清单只有群组名,缺 groupId 无需改脚本;在 SKILL.md 注明前置依赖即可

差异分为两类:脚本缺陷按钮定位、base64 解码、伪头过滤)应回填到技能脚本;环境/规模差异(下载目录、批量循环、前置补 ID属于执行时的合理适配脚本本身逻辑无需破坏性改动。


七、四技能优化清单(建议)

youtube-studio-csv-download高优先

  1. 导出按钮定位由 get_by_text 改为 get_by_label("导出当前视图")(保留文本定位兜底)。
  2. decode_zipped_data 改为 URL-safe base64 解码(补 = + altchars=b"-_")。
  3. (可选增强)保存后加 zipfile.testzip() 校验,失败自动重试一次。

yt-studio-groupid-lookup中优先

  1. 捕获套件时自动过滤 HTTP/2 伪头(:authority / :method / :path / :scheme)。
  2. (可选)运行前探测 Chrome 残留进程,给出更明确的"完全退出后重启"提示。

uv-env-setup低优先

  1. 补充"uv 命令不可用时改用 python -m uv 或直调 .venv\Scripts\python.exe"的排查提示。

yt-studio-url-builder低优先

  1. SKILL.md 显式说明"清单只有群组名时,需先经 groupid-lookup 补 entity_id"。

八、待确认事项

以上优化点(尤其第三节、第五节的 3 处脚本缺陷修复)尚未改动任何技能脚本,仅记录在本文档。是否执行优化、执行到哪些范围(仅修复缺陷 / 同时做增强),请确认后再实施。