资讯动态

gdown 浏览器 Cookie 提取方案剖析:以符号级 Vendor 方式引入 yt-dlp 的 Cookie 模块

发布时间:2026/10/13 6:48:41 来源:尧图企业网站定制
CLI开发工具【免费下载链接】gdownGoogle Drive public file downloader when curl/wget fails.项目地址https://gitcode.com/gh_mirrors/gd/gdown点击查看免费下载导读Google Drive 会对访问量过大的公共文件触发“Too many users have viewed or downloaded this file recently”限流但对已登录账户却照常放行。gdown 通过一项名为「符号级 Vendorsymbol-level vendoring」的架构决策把 yt-dlp 的浏览器 Cookie 提取模块以最小代价引入项目既没有新增运行时依赖也让gdown --cookies-from-browser firefox URL开箱即用。本文基于仓库中的架构决策记录 docs/adr/0002-vendor-ytdlp-cookie-extraction.md结合gdown/_vendor/下的生成代码与手写 shim、CLI 入口和测试用例讲清这条决策从“为什么”到“怎么用”再到“如何维护”的完整链路。背景Drive 限流与“登录账户可下载”的矛盾Google Drive 对热门的公共文件执行限流当短时间内访问人数过多时服务端会拒绝匿名下载。ADR 记录于 2026-09-04 实测验证一个被限流的 Newer College rosbag 文件不带 Cookie 时下载失败而换上已登录浏览器的 Google Cookie 后即可正常下载。在此之前gdown 其实已经支持 Cookie但使用门槛很高用户必须先用浏览器扩展把 Cookie 导出成 Netscape 格式的cookies.txt再手动放进缓存目录。yt-dlp 与 gallery-dl 早已确立了更顺手的 CLI 约定——--cookies FILE指定文件、--cookies-from-browser BROWSER直接从浏览器读取——而 gdown 的诉求是uvx gdown必须无需任何额外步骤就能工作。从技术实现看读取浏览器 Cookie 库并不轻松要碰 SQLite 数据库、按平台取密钥Linux 的 GNOME Keyring / KWallet、macOS 的 Keychain、Windows 的 DPAPI、再走 AES 解密。浏览器提取是 gdown 中唯一一个纯 CLI 场景的功能而 gdown 的大部分安装形态是把 gdown 当库使用因此为它引入新的运行时依赖很难有正当理由。备选方案评估为什么最终选择 VendorADR 逐一推演了四条替代路线并给出否决理由方案评估结论否决原因依赖 browser-cookie3否决LGPL 许可证自带 36 个传递依赖其中 2 个是 C 扩展上游自 2024 年 12 月起基本停更。每个库的使用者都要为一个 CLI 功能买单且 LGPL 代码无法在日后想卸掉依赖时复制进 MIT 项目直接依赖 yt-dlp否决为了一个函数引入约 3 MB 的依赖代价不成比例从 gallery-dl 复制代码否决gallery-dl 是 GPL-2 许可证不能并入 MIT 项目从 yt-dlp Vendor采用cookies.py与纯 Python 的aes.py以 Unlicense公有领域发布仅需标准库加系统工具且上游持续维护作为可选 extra 发布否决extras 只会“加依赖”无法表达精简的gdown[core]uvx gdown也拿不到该功能另有一个所有方案都无法绕开的硬约束Google 的 App-Bound Encryption应用绑定加密使得没有任何方案能在 Windows 上无管理员权限读取 Chrome 127 的 Cookie而 Firefox 在所有平台上都可以读取。这个约束直接决定了后面的平台策略。决策符号级 Vendor 与一键再生成脚本最终决策是对 yt-dlp 的 Cookie 模块做符号级提取symbol-level extraction。仓库中的 scripts/vendor_ytdlp_cookies.py 是这个流程的执行者其工作机制清晰可见锁定一个 yt-dlp 发布 tag脚本默认值TAG 2026.08.19从 yt-dlp 仓库在线下载yt_dlp/cookies.py与yt_dlp/aes.py两个模块以extract_cookies_from_browser和SUPPORTED_BROWSERS为根ROOTS用ast遍历其顶层定义引用的闭包只保留可达的符号把保留的源码连同必要的标准库 import 写进唯一一个生成文件 gdown/_vendor/_ytdlp_cookies.py。该生成文件以头注释明示来源与纪律# Generated by scripts/vendor_ytdlp_cookies.py from yt-dlp 2026.08.19.、# Do not edit; rerun the script to upgrade.、# yt-dlp is public domain (Unlicense).并带有# ruff: noqa、# fmt: off从工具链上杜绝手工改动。升级流程就是换一个更新的 tag 重跑脚本例如uv run python scripts/vendor_ytdlp_cookies.py 2026.09.01脚本在写入后会做一次自检比对 shim 中是否缺少提取代码引用的名字若缺则报错并提示需要扩展 shim见下文。生成文件的头部可以看到完整的浏览器清单与入口函数CHROMIUM_BASED_BROWSERS {brave, chrome, chromium, edge, opera, vivaldi, whale} SUPPORTED_BROWSERS CHROMIUM_BASED_BROWSERS | {firefox, safari} def extract_cookies_from_browser(browser_name, profileNone, loggerYDLLogger(), *, keyringNone, containerNone): if browser_name firefox: return _extract_firefox_cookies(profile, container, logger) elif browser_name safari: return _extract_safari_cookies(profile, logger) elif browser_name in CHROMIUM_BASED_BROWSERS: return _extract_chrome_cookies(browser_name, profile, keyring, logger) else: raise ValueError(funknown browser: {browser_name})手写 shim把“纯复制”与“手工维护”分开提取出的 yt-dlp 代码会 import 十几个 yt-dlp 内部符号它的 logger、进度条打印机、subprocess 包装器以及若干小的字符串辅助函数。这些符号放在紧邻生成文件的手写 shimgdown/_vendor/_ytdlp_shim.py 中实现两个目标生成文件保持纯复制它本身绝不掺入手写代码升级时可整文件替换手写面保持最小shim 全文约一百余行且文件头部明确写着“每个名字的调用形态尽量贴近上游仅供提取代码使用gdown 自身不直接使用”。shim 提供的替代实现包括_YDLLoggerdebug/info/warning/error 四种日志通道、MultilinePrinter与QuietMultilinePrinter进度输出、Popen基于subprocess.Popen的run类方法统一 stdout/stderr 与超时语义、CryptodomeAES None让提取的 AES 代码在没有 pycryptodomex 时走纯 Python 路径、以及compat_ord、error_to_str、is_path_like、str_or_none、try_call、write_string、normalize_url、sanitize_url等辅助函数。值得注意的一个设计细节shim 中有一个模块级探测函数_probe_secretstorage()它在 import 时尝试加载secretstorage模块失败时记录原因字符串并置secretstorage None、_SECRETSTORAGE_UNAVAILABLE_REASON。这使提取的 Chromium 解密代码在 GNOME Keyring 缺失时能给出明确诊断而不是神秘报错。CLI 集成一次复制、之后免 flag两个命令行参数沿用了 yt-dlp 的命名定义于 gdown/main.py--cookies FILE读写 Netscape 格式 Cookie 文件默认~/.cache/gdown/cookies.txt--cookies-from-browser BROWSER从指定浏览器复制 Google Cookie 到 Cookie 文件choices直接取自生成文件的SUPPORTED_BROWSERS在BROWSERS常量中排序导出--no-cookies完全不读不写 Cookie且与上述两个参数互斥解析期即报错。CLI 的核心流程是下载开始前只做一次浏览器 Cookie 导入之后库层始终保持单一的 Cookie 来源同一个 Cookie 文件后续运行无需再带任何参数。调用链位于 gdown/download.py 的_import_cookies_from_browser()函数内部延迟导入vendor 模块——只有真的用到浏览器提取时才加载保证库用户零成本调用extract_cookies_from_browser(browser, loggerlogger)提取全部 Cookie然后只保留google.com及.google.com域的条目通过专门的_CookieExtractionLogger收集 keyring 与解密告警一旦记录到 error即使有“看起来解密成功”的 Cookie 也整体放弃防止空口令回退把坏数据写进文件抛DownloadError对 Chromium 家族做过期时间换算Chromium 以 1601 年起算的微秒存储到期时间需要expires // 1_000_000 - 11_644_473_600转成 Unix 时间戳避免把已过期 Cookie 存成“远未来”合并写入 Cookie 文件并返回导入数量。__main__.py中的处理逻辑gdown/main.py随后给出反馈成功时打印Saved N Google cookies from browser to file找不到任何 Google Cookie 时提示“先在浏览器中登录 Google或改用其它浏览器”并退出码 1导入失败时打印错误详情若在 Windows 且浏览器不是 Firefox还会追加提示Chrome 127 on Windows blocks other programs from reading its cookies. Try --cookies-from-browser firefox.一条完整可用的命令如下README 中的示例见 README.md# 以已登录账号身份下载直接复用浏览器的 Cookie gdown https://drive.google.com/uc?idFILE_ID --cookies-from-browser firefox # 用独立文件保存/读取 Cookie覆盖默认路径 gdown https://drive.google.com/uc?idFILE_ID --cookies ./cookies.txt # 完全禁用 Cookie gdown https://drive.google.com/uc?idFILE_ID --no-cookiesCookie 文件的生命周期会话 Cookie 与权限安全“Cookie 文件里存着整个 google.com 会话含 Gmail 与账户信息”是必须严肃对待的事实。代码层面有两处对应的硬措施gdown/download.py_load_cookies()以ignore_discardTrue, ignore_expiresTrue加载因为Google 的登录状态有一部分活在会话 Cookie 里而 Netscape 格式默认会丢弃它们加载后把expires 0的会话 Cookie 改为不过期标准库否则会视为已过期再统一清理真正过期的条目_save_cookies()在写入任何字节之前就用mode0o600创建文件并os.chmod(..., 0o600)确保只有当前用户可读。README 明确要求把这个文件当成密码对待需要吊销时就删除该文件并在浏览器中退出 Google 登录。测试用例印证了这两点tests/test_download.py 中覆盖了「多次导入不重复、合并保留已有 Cookie」「导入后文件权限为 0o600」「keyring 失败时保留原有的好会话、绝不写入坏数据」「Chromium 过期时间换算」「扩展导出 Cookie 的会话保留」等场景。GNOME Keyring用 optional extra 补最后一公里Linux 上 Chromium 系浏览器的 Cookie 密钥存放在系统钥匙串中yt-dlp 的惯例是通过secretstorage这个 Python 包访问 GNOME Keyring。gdown 遵循同样的 optional-extra 约定pyproject.toml[project.optional-dependencies] secretstorage [secretstorage]主依赖列表保持原样beautifulsoup4、filelock、requests[socks]、tqdm等见 pyproject.toml没有为 CLI 功能新增任何运行时依赖。安装方式pip install gdown[secretstorage] # 或在不污染环境的情况下临时使用 uvx --from gdown[secretstorage] gdown --cookies-from-browser chrome URLFirefox 在 Linux 上不需要任何额外依赖其 Cookie 数据库本身未加密这也是建议优先使用 Firefox 的原因之一。若secretstorage缺失shim 中的探测会生成类似“as thesecretstoragemodule is not installed. Install withpip install gdown[secretstorage]”的提示直接告诉用户该装什么。平台限制速查平台可用性所有平台Firefox 均可读取无需额外依赖macOSChromium 系首次会请求一次登录密码以解锁 KeychainSafari 需要为终端授予“完全磁盘访问权限”Full Disk AccessLinuxChromium 系若使用 GNOME Keyring 需gdown[secretstorage]KWallet 走kwallet-query经 dbusWindowsChrome 127 因 App-Bound Encryption 无法被其他程序读取官方提示改用 Firefox后果与维护契约这条 ADR 决策写下了一组可以验证的后果uvx gdown --cookies-from-browser firefox URL无额外依赖、无额外配置即可工作约 1600 行生成代码常驻仓库当前生成文件实际约 1650 行被ruff: noqa/fmt: off排除在 lint 与类型检查之外且只在重跑脚本时变化上游一旦重命名内部符号两处会同时“大声失败”一是脚本结束时的 shim 缺失名报告二是生成模块的 import 错误——这正是扩展 shim 的信号支持浏览器清单与锁定的 yt-dlp 发布版保持一致升级 tag 即随上游更新浏览器清单由SUPPORTED_BROWSERS一处定义CLI 的choices与测试中的断言如 tests/test___main__.py 的test_browser_choices_match_vendored_extractor都指向同一个来源防止两者漂移Windows Chrome 用户得到的是指向 Firefox 的明确错误提示而不是神秘的解密失败。整体来看这一设计把“功能完整”与“依赖克制”同时做到了提取代码是上游公有领域源码的机械副本可审计、可整体升级手写 shim 是唯一需要人工维护的薄接口CLI 与库层通过 Cookie 文件解耦库用户与uvx用户各取所需。如果你想深入了解实现细节可以从 scripts/vendor_ytdlp_cookies.py生成器、gdown/_vendor/_ytdlp_shim.pyshim、gdown/download.py导入与存取逻辑和 tests/test_download.py行为契约四条线索继续深入。赞分享CLI开发工具【免费下载链接】gdownGoogle Drive public file downloader when curl/wget fails.项目地址https://gitcode.com/gh_mirrors/gd/gdown点击查看免费下载相关推荐深入解析js-cookie轻量级浏览器Cookie处理库深入解析js cookie轻量级浏览器Cookie处理库 js cookie是一个轻量级、功能强大的JavaScript Cookie处理库以其简洁的API前端Clank高级技巧创建复杂移动应用导航和页面转场效果Clank高级技巧创建复杂移动应用导航和页面转场效果 Clank是一款强大的开源移动应用原型开发框架能够帮助开发者快速构建具有专业级用户体验的移动应用界面。前端UI库/组件Super Productivity Cookie浏览器Cookie管理Super Productivity Cookie浏览器Cookie管理 痛点Jira集成认证的复杂性 你是否曾经遇到过这样的困境在使用Super Pro前端桌面应用移动开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑