应使用 page.route() 拦截视频 MIME 类型响应并调用 response.body() 获取二进制数据,需确保响应成功、等待加载完成、校验文件大小与格式;对非网络生成的 Blob,须注入 JS 重写 URL.createObjectURL 提取 ArrayBuffer。

Playwright 中如何拦截并保存 Blob URL 对应的视频?
Playwright 本身不直接解析 Blob URL(如 blob:https://example.com/xxx),因为这类 URL 是浏览器内存中的引用,服务端无真实路径。必须通过拦截网络请求或监听 response 事件,捕获其原始二进制内容。
关键点在于:不能用 page.goto(blobUrl) —— 这会触发跨源错误或空白页;也不能靠 page.download(),它只响应 Content-Disposition 头的下载请求,而 Blob 流通常没有。
- 正确做法是监听页面中可能触发 Blob 创建的 JS 调用(如
URL.createObjectURL())或更可靠的——拦截后续由该 Blob 触发的真实资源请求(例如fetch()或XMLHttpRequest返回的视频流) - 实践中最稳定的方式是启用
page.route()拦截匹配视频 MIME 类型(如"video/mp4"、"video/webm")的响应,并用response.body()获取原始 bytes - 注意:需在导航前设置 route,且要允许通配(如
**/*),否则可能错过动态生成的请求
如何确保下载的 Blob 视频文件完整且可播放?
仅保存 response.body() 不够——常见坑是响应未完全加载就调用 body(),导致截断;或忽略 response.headers 中的 content-length 与实际 body 长度不一致问题。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
- 务必等待
response.status == 200且response.ok为True - 优先使用
response.body()(而非response.text()),避免编码转换破坏二进制 - 校验建议分两步:① 写入临时文件后用
os.path.getsize()确认非零;② 用ffprobe(需提前安装)检查是否为有效视频容器:ffprobe -v error -show_entries format=duration -of default=nw=1 "video.mp4"
- 若视频含加密(如 MSE + EME),则无法通过常规 route 拦截获取明文流——此时需 hook
MediaSource或监听sourceopen事件,复杂度陡增
为什么 page.route() 拦不到某些 Blob 视频请求?
根本原因是:不是所有 Blob 都来自网络请求。有些视频数据直接由 JS ArrayBuffer 构造,再通过 URL.createObjectURL(new Blob([arrayBuffer])) 创建,全程不经过网络栈,page.route() 完全不可见。
立即学习“Python免费学习笔记(深入)”;
- 这种场景下,唯一可行路径是注入 JS 监听
window.URL.createObjectURL,重写它并提取传入的Blob对象,再用blob.arrayBuffer()转为 bytes(需配合page.evaluate_handle()和handle.json_value()或handle.object_id跨上下文传递) - 但注意:Playwright 的
evaluate上下文无法直接读取Blob.arrayBuffer()返回的 Promise 结果,必须用page.evaluate(async () => {...})并 await - 更隐蔽的坑:部分站点用
ReadableStream+pipeTo()动态写入MediaSource,此时连createObjectURL都不调用——只能靠page.on("console")监听调试日志,或逆向分析其分片加载逻辑
校验视频完整性时最容易忽略的细节
很多人用 hashlib.md5(file_bytes) 做一致性比对,却忘了服务端返回的视频可能带 HTTP 分块编码(chunked transfer encoding)或压缩(如 gzip),而 Playwright 的 response.body() 默认返回解压后的原始内容——这本身没错,但若想和服务器原始响应比对,就必须禁用自动解压。
- Playwright 当前(v1.40+)不支持关闭自动解压,所以 MD5 校验只能用于“本地多次下载是否一致”,不能用于“与服务端原始 payload 一致”
- 真正可靠的端到端校验方式是:在
page.route()中用route.fulfill()记录原始response.headers和未解压的response.body()(需开启--disable-http-cache启动浏览器并禁用 service worker) - 最后提醒:Blob 视频常被前端加水印或做 canvas 帧处理,此时即使下载成功,得到的也不是原始源文件——这是业务层限制,技术上无法绕过

















