ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Claude Code实战:用Python抓包捕获隐藏视频链接并下载到TaoToken

Claude Code实战:用Python抓包捕获隐藏视频链接并下载到TaoToken 1. 网页视频链接为什么总是“藏起来”很多人第一次做视频下载都会卡在同一个地方明明浏览器里视频播放得好好的打开开发者工具却找不到一个能直接右键保存的.mp4。这不是你操作有问题而是现在主流网课、直播回放、在线教育平台几乎都换成了流媒体分发方式。页面里播放的那段视频往往不是一整个文件而是被切成几百上千个小片段通过播放列表动态拼接出来的。你看到的“一个视频”在网络上其实是“一串请求”。我拿一个真实场景举例。有位朋友给孩子买了网课直播时没空看回放又是限时的过期就打不开了。他想把视频存到本地试过录屏一个多小时录下来画质掉得厉害还特别占时间。后来他换了个思路既然视频能在浏览器里播那播放器一定向某个地址发起了请求只要把这个地址找出来就能直接下载原始文件。这个思路是对的问题在于怎么高效地把地址找出来。传统做法是打开浏览器开发者工具切到 Network 面板勾选 Media 过滤然后刷新页面在一堆请求里肉眼找.m3u8或.mp4。这个方法能用但有几个明显的坑。第一请求太多媒体请求混在图片、脚本、接口里筛选条件稍微不对就漏掉。第二很多平台的视频地址带签名参数过期时间很短你手动复制下来可能已经失效。第三遇到 HLS 流你拿到的是.ts分片单独下载一个没法播放必须找到.m3u8播放列表再合并。第四部分地址有 Referer 防盗链直接下载返回 403。所以真正省事的做法是让程序自动完成“抓取请求 → 过滤媒体地址 → 提取播放列表 → 下载合并”这一整条链路。这也是本文要讲的核心用 Claude Code 配合 Python写一个能自动定位隐藏视频链接并下载的工具。它适合有基础 Python 环境、想批量保存授权范围内视频的读者比如自己购买的课程、公司内部培训回放等。下面我会把可复制的配置、脚本和排障步骤都给出来你跟着做就能跑通。需要先说明一点本文所有操作都建立在你有权访问并保存这些视频的前提下比如自己购买的课程、自己录制的直播回放。请勿用于侵犯他人版权或绕过平台授权的场景。2. TaoToken 前置给 Claude Code 配好模型入口Claude Code 本身是一个命令行里的编码助手它能读你的项目文件、写代码、跑命令、根据报错自动修复。但它的“大脑”需要接一个大模型。默认情况下它连的是官方服务国内访问不稳定而且计费方式对个人开发者不太友好。更实际的做法是把它接到一个兼容 Anthropic 接口的模型服务上TaoToken 就是这样一个入口它提供 Claude Code 需要的 API 地址和密钥你只需要改几个环境变量就能用。先说清楚 TaoToken 在这里的角色它不是抓包工具也不替代你的编辑器它只是给 Claude Code 提供模型推理能力。抓包和下载的逻辑仍然是 Claude Code 帮你写出来的 Python 代码在跑。所以整个链路是TaoToken 提供模型 → Claude Code 负责写代码和排障 → Python 脚本负责实际抓取和下载。配置方式有两种一种是临时环境变量一种是写进配置文件。临时方式适合快速试一下写进配置文件适合长期用。先看临时方式在终端里执行export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_AUTH_TOKEN你的TaoToken密钥Windows 的 PowerShell 里写法不同$env:ANTHROPIC_BASE_URLhttps://taotoken.net/api $env:ANTHROPIC_AUTH_TOKEN你的TaoToken密钥密钥在 TaoToken 控制台的 API Keys 页面创建地址是 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite 。创建后复制那一串以sk-开头的字符串粘贴到上面的ANTHROPIC_AUTH_TOKEN位置。如果你希望每次打开终端都自动生效可以写进 shell 配置文件。macOS 和 Linux 用户编辑~/.zshrc或~/.bashrc加上刚才那两行 export。Windows 用户可以在系统环境变量里新建这两个变量或者用 Claude Code 自己的配置文件。Claude Code 还支持一个settings.json配置文件路径通常在用户目录下的.claude文件夹里。你可以直接写一个 JSON 片段把模型入口固定下来{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: 你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-5-20250929 } }这里三个字段要配齐Base URL 指向 TaoToken 的 API 地址Key 是你的密钥Model ID 指定用哪个模型。Model ID 可以按需换成你账号里可用的其他模型。配好之后在项目目录里运行claude如果能看到欢迎界面并且底部显示模型名称说明接入成功。有一点要注意Base URL 写https://taotoken.net/api就行不要在后面加多余的路径。密钥不要提交到 Git 仓库也不要在截图里暴露。如果你在团队里共用建议每个人用自己的密钥方便在控制台看用量。配好模型入口之后Claude Code 就能正常对话和写代码了。接下来我们进入正题让它帮我们写一个抓包分析工具。你可以先在项目目录里建一个空文件夹比如getpacket然后cd进去运行claude把需求描述清楚。描述需求时越具体越好比如告诉它“我要一个 Python 工具能列出系统进程、对选中进程抓包、提取视频链接”它就会进入计划模式先给你一份实现方案你确认后再动手写。3. 可复制配置抓包过滤与下载脚本这一节是全文的核心我会把关键配置和脚本片段给出来。你不需要全部手敲可以让 Claude Code 生成但理解每一段在做什么排障时才有方向。先说抓包方案的选择。直接抓网卡原始数据包只能看到加密后的 HTTPS 流量拿不到里面的 URL。要解密 HTTPS需要用中间人代理的方式本地起一个代理服务把系统流量导过去代理用自签证书解密后再转发。Python 生态里mitmproxy就是干这个的它支持写 addon 脚本在请求经过时把 URL 和请求头打印出来。抓包过滤的核心逻辑是判断一个请求是不是视频。判断依据有几类URL 后缀是不是.mp4、.m3u8、.ts、.flv、.mpd响应头的Content-Type是不是video/*或application/vnd.apple.mpegurlURL 里有没有video、stream、m3u8这类关键词。下面是一个 mitmproxy addon 的配置片段保存为addons/video_extractor.pyfrom mitmproxy import http import json import sys class VideoExtractor: def __init__(self): self.video_extensions { .mp4, .m3u8, .flv, .ts, .mkv, .avi, .f4v, .webm, .m4s, .mpd } self.video_keywords [video, stream, media, play, hls, mpeg] def request(self, flow: http.HTTPFlow): url flow.request.pretty_url url_lower url.lower() # 优先识别 m3u8 播放列表 if .m3u8 in url_lower: self._emit(flow, url, m3u8_playlist) return # 识别视频文件后缀 if any(url_lower.endswith(ext) for ext in self.video_extensions): self._emit(flow, url, video) return # 关键词 后缀双重判断降低误报 if any(kw in url_lower for kw in self.video_keywords): if any(ext in url_lower for ext in [.mp4, .m3u8, .flv, .ts, .mpd]): self._emit(flow, url, video) def response(self, flow: http.HTTPFlow): if not flow.response: return ct flow.response.headers.get(content-type, ).lower() if mpegurl in ct or m3u8 in ct: self._emit(flow, flow.request.pretty_url, m3u8_playlist) elif video in ct or dash in ct: self._emit(flow, flow.request.pretty_url, video) def _emit(self, flow, url, kind): headers {} for key in [Referer, User-Agent, Origin, Authorization, Cookie]: value flow.request.headers.get(key, ) if value: headers[key] value info {url: url, type: kind, headers: headers} print(f[VIDEO] {json.dumps(info, ensure_asciiFalse)}) sys.stdout.flush() addons [VideoExtractor()]这段脚本的关键点在于它把 URL 和请求头一起输出成 JSON尤其是Referer。很多平台用 Referer 做防盗链你下载时如果不带这个头服务器直接返回 403。所以抓取阶段就要把 Referer 存下来下载阶段原样带上。启动 mitmproxy 并加载这个 addon命令是mitmdump --listen-host 127.0.0.1 --listen-port 8080 -s addons/video_extractor.py启动后把系统代理指向127.0.0.1:8080。Windows 可以在“设置 → 网络和 Internet → 代理”里手动填也可以用脚本改注册表。macOS 在“系统设置 → 网络 → 代理”里配置。配置完代理后第一次访问 HTTPS 网站会提示证书不受信任需要把 mitmproxy 的 CA 证书装到系统信任区。证书文件在用户目录的.mitmproxy文件夹里文件名是mitmproxy-ca-cert.pem。Windows 用管理员权限执行certutil -addstore -f ROOT %USERPROFILE%\.mitmproxy\mitmproxy-ca-cert.pem装完证书后重启浏览器再播放视频终端里就会刷出[VIDEO]开头的行。拿到 m3u8 地址和 Referer 之后就是下载环节。HLS 视频的下载逻辑是先请求 m3u8 文件解析出所有.ts分片地址如果 m3u8 里有#EXT-X-KEY行说明分片是 AES-128 加密的要先下载密钥然后逐个下载分片、解密、按顺序拼接成一个文件。下面是一个精简版的下载脚本hls_download.pyimport argparse import os import re import struct import tempfile import urllib.parse from typing import List, Optional, Tuple import requests try: from Crypto.Cipher import AES HAS_CRYPTO True except ImportError: HAS_CRYPTO False class HLSDownloader: def __init__(self, referer: str , user_agent: str ): self.referer referer self.user_agent user_agent or ( Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 ) self.session requests.Session() self.session.headers.update({User-Agent: self.user_agent}) if referer: self.session.headers[Referer] referer def fetch(self, url: str, binary: bool False): resp self.session.get(url, timeout30) resp.raise_for_status() return resp.content if binary else resp.text def parse_m3u8(self, content: str, base_url: str) - Tuple[List[str], Optional[dict]]: ts_urls [] key_info None base_dir base_url.rsplit(/, 1)[0] for line in content.splitlines(): line line.strip() if line.startswith(#EXT-X-KEY:): key_info self._parse_key(line, base_url) elif line and not line.startswith(#): if not line.startswith(http): if line.startswith(/): p urllib.parse.urlparse(base_url) line f{p.scheme}://{p.netloc}{line} else: line f{base_dir}/{line} ts_urls.append(line) return ts_urls, key_info def _parse_key(self, line: str, base_url: str) - Optional[dict]: info {} m re.search(rMETHOD([^,]), line) if m: info[method] m.group(1) m re.search(rURI([^]), line) if m: uri m.group(1) if not uri.startswith(http): base_dir base_url.rsplit(/, 1)[0] uri f{base_dir}/{uri} info[uri] uri m re.search(rIV0x([0-9a-fA-F]), line) if m: info[iv] bytes.fromhex(m.group(1)) return info or None def download(self, m3u8_url: str, output: str) - bool: content self.fetch(m3u8_url) # 处理嵌套 m3u8 if .m3u8 in content and #EXT in content: for line in content.splitlines(): line line.strip() if .m3u8 in line and not line.startswith(#): if not line.startswith(http): base_dir m3u8_url.rsplit(/, 1)[0] line f{base_dir}/{line} return self.download(line, output) ts_urls, key_info self.parse_m3u8(content, m3u8_url) if not ts_urls: print(未解析到分片地址) return False print(f共 {len(ts_urls)} 个分片) key None if key_info and key_info.get(method) AES-128 and key_info.get(uri): if not HAS_CRYPTO: print(需要安装 pycryptodome: pip install pycryptodome) return False key self.fetch(key_info[uri], binaryTrue)[:16] print(检测到 AES-128 加密已获取密钥) tmp_dir tempfile.mkdtemp(prefixhls_) files [] for i, url in enumerate(ts_urls): data self.fetch(url, binaryTrue) if key: iv key_info.get(iv) or (struct.pack(I, i) b\x00 * 12) cipher AES.new(key, AES.MODE_CBC, iv) data cipher.decrypt(data) path os.path.join(tmp_dir, fseg_{i:05d}.ts) with open(path, wb) as f: f.write(data) files.append(path) print(f\r下载进度 {i 1}/{len(ts_urls)}, end) print() with open(output, wb) as out: for path in files: with open(path, rb) as f: out.write(f.read()) size os.path.getsize(output) / 1024 / 1024 print(f完成: {output} ({size:.2f} MB)) return True def main(): parser argparse.ArgumentParser(descriptionHLS 视频下载工具) parser.add_argument(url, helpm3u8 或 mp4 地址) parser.add_argument(-r, --referer, default, helpReferer 头) parser.add_argument(-u, --user-agent, default, helpUser-Agent 头) parser.add_argument(-o, --output, defaultvideo.mp4, help输出文件名) args parser.parse_args() dl HLSDownloader(args.referer, args.user_agent) if args.url.endswith(.mp4): data dl.fetch(args.url, binaryTrue) with open(args.output, wb) as f: f.write(data) print(f完成: {args.output}) else: dl.download(args.url, args.output) if __name__ __main__: main()依赖装两个就够pip install requests pycryptodome用法很直接把抓到的 m3u8 地址和 Referer 填进去python hls_download.py https://example.com/video/index.m3u8 -r https://example.com/ -o lesson01.mp4如果是直接的 mp4 地址脚本会走另一条分支直接下载。这里有个细节AES-128 的 IV 如果 m3u8 里没写默认用分片序号构造脚本里已经处理了。分片下载顺序必须严格按 m3u8 里的顺序否则拼出来的视频会花屏或音画不同步。4. 验证请求从抓包到文件落地的完整结果配置写完之后最重要的是验证整条链路真的通了。我按实际操作顺序拆成几步每一步都有明确的成功标志你可以对照检查。第一步启动抓包服务。在项目目录运行mitmdump命令看到类似Proxy server listening at http://127.0.0.1:8080的输出说明代理起来了。这时候系统代理还没配浏览器流量不会经过它。配好系统代理后随便打开一个 HTTPS 网站终端里应该开始刷请求日志。如果一条都没有说明代理没生效回去检查系统代理设置。第二步播放目标视频。在浏览器里打开你要保存的课程或回放点播放。终端里会刷出[VIDEO]开头的 JSON 行。你要找的是type: m3u8_playlist的那条它的url字段就是播放列表地址headers里的Referer就是下载时要带的头。如果只看到一堆.ts分片地址没看到 m3u8说明你是在视频播放中途才开始抓的播放列表请求已经过去了。解决办法是停止抓包、清空日志然后从头刷新页面重新播放让播放列表请求重新出现。第三步复制地址和 Referer。把 m3u8 的 URL 和 Referer 值分别复制出来。注意 Referer 通常只到域名比如https://live-web.example.com/不要多复制路径。有些平台的 Referer 带完整路径那就原样复制。第四步运行下载脚本。把地址和 Referer 填进命令python hls_download.py https://stream.example.com/xxx/index.m3u8?idabc -r https://live-web.example.com/ -o lesson01.mp4成功的话终端会先打印分片总数然后进度条一路走到 100%最后输出文件大小。我实测一个 189 个分片的课程下载加解密加合并大概两分钟输出文件 185 MB 左右。用播放器打开画面和声音都正常拖动进度条也没问题。第五步校验文件完整性。下载完成后可以用ffprobe看一下时长和编码信息ffprobe -v error -show_entries formatduration,size -of defaultnoprint_wrappers1 lesson01.mp4如果输出的时长和课程实际时长对得上说明分片没漏。如果时长明显偏短可能是某些分片下载失败被跳过了需要重新下载。脚本里对失败分片是跳过处理的生产环境可以改成重试三次。这里再补充一个常见情况有些平台的 m3u8 是嵌套的主播放列表里只有一行子 m3u8 地址真正的分片列表在子文件里。脚本里已经做了递归处理遇到嵌套会自动往下解析。如果你手动看 m3u8 内容发现里面只有#EXT-X-STREAM-INF加一行地址那就是嵌套结构交给脚本处理就行。验证通过之后你就有了一个可复用的流程抓包拿地址 → 填参数下载 → 校验文件。下次遇到同类视频重复这几步即可。如果视频很多可以把地址和 Referer 写进一个列表循环调用下载函数实现批量保存。5. 本篇常见错排查403、证书、分片失败实际操作中报错是难免的。我把几个高频问题和对应的排查思路整理出来你遇到时可以直接对照。403 Forbidden提示 denied by Referer ACL。这是最常见的错误原因是下载请求没带 Referer或者 Referer 值不对。服务器通过 Referer 判断请求来源来源不合法就拒绝。解决办法是把抓包时记录的 Referer 原样带上。如果你用的是requests检查session.headers里有没有设置Referer。如果带了还是 403可能是 Referer 需要精确到某个路径或者还需要Origin头。把抓包输出里的Origin也一起带上试试。还有一种情况是地址带签名参数且已过期重新抓一次拿新地址。证书报错浏览器提示连接不安全。这是 mitmproxy 的 CA 证书没装到系统信任区。表现是配了代理之后所有 HTTPS 网站都打不开或者视频加载失败。解决办法是按前面说的用certutil命令把mitmproxy-ca-cert.pem装到“受信任的根证书颁发机构”。装完之后浏览器和部分应用需要完全重启才能识别新证书。注意是重启进程不是关标签页。如果重启后还不行检查证书是不是装到了“个人”而不是“受信任的根证书颁发机构”。ImportError: cannot import name controller from mitmproxy。这是 mitmproxy 版本升级导致的 API 变化旧代码里from mitmproxy import controller在新版本里已经移除。解决办法是不要直接调用 mitmproxy 的 Python API改用命令行方式启动mitmdump通过-s加载 addon 脚本。这样版本兼容性最好也更容易调试。分片下载失败输出文件时长偏短。原因可能是某个分片请求超时或者被限流。脚本里对失败分片是跳过的所以文件能生成但不完整。排查方法是看下载日志里有没有跳过的分片序号然后单独重试那个分片。更稳妥的做法是给fetch加重试逻辑失败后等一秒再试最多三次。另外分片下载不要太快有些服务器对高频请求会限流可以在每个分片之间加一个短 sleep。下载下来的文件无法播放或者只有声音没画面。这通常是解密环节出了问题。检查 m3u8 里有没有#EXT-X-KEY行如果有确认密钥下载成功、IV 计算正确。AES-128 的 IV 如果 m3u8 里指定了IV0x...必须用指定的值如果没指定才用分片序号构造。用错了 IV解密出来的数据是乱的播放器识别不了。还有一种可能是分片顺序错了检查拼接时是不是严格按 m3u8 里的顺序。抓包抓不到任何视频请求。先确认系统代理是否真的生效可以在浏览器里访问一个显示 IP 的网站看出口 IP 有没有变。如果没变说明代理没配上。其次确认目标应用是不是走了系统代理有些播放器用自己的网络栈不读系统代理设置。这种情况需要在应用内单独配置代理或者用透明代理模式。最后确认证书装好了证书没装的话 HTTPS 请求会直接失败日志里也不会有内容。进程列表里一堆 msedgewebview2分不清哪个是浏览器。WebView2 是很多桌面应用内嵌的浏览器组件不只是 Edge 在用。区分方法是看进程的窗口标题和父进程。浏览器主进程通常有明确的窗口标题WebView2 组件的标题可能是空的或者显示宿主应用名。如果只是想抓浏览器里的视频直接在浏览器里操作不用纠结选哪个进程因为系统代理抓的是全局流量跟选哪个进程无关。6. 语义一致 CTA把工具用起来到这里抓包、解析、下载、排障的完整链路就讲完了。你可以按这个顺序动手先用 TaoToken 把 Claude Code 的模型入口配好让它帮你生成和调试脚本然后启动 mitmproxy 抓包定位 m3u8 地址和 Referer最后用下载脚本把视频保存到本地。整个过程里Claude Code 负责写代码和修 bug你负责确认需求和验证结果。如果你在配置模型入口时遇到问题比如密钥无效、模型名不对可以去 TaoToken 的接入文档看详细说明https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite 。文档里有各种客户端的配置示例包括 Claude Code、Cline、Codex 这些。想先试试模型对话效果可以打开 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite 直接体验。如果你打算长期用 Claude Code 做编码和 Agent 任务Coding Plan 会更划算地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewrite 。最后提醒一句抓包和下载技术本身是中性的用在自己有权访问的内容上是合理的比如自己买的课、自己录的回放。用之前确认一下平台的授权范围别把工具用在侵犯版权的地方。工具是死的怎么用取决于人。
返回列表