当前位置:首页 > 百科

python如何爬取网页视频

用 requests 库直接去抓 B 站视频地址,何爬十有八九会拿到一个 403。取网不是页视代码写错了,是何爬服务器一眼就看出你不是浏览器。视频网站防爬的取网第一道门槛从来不是技术,是页视身份识别。

我拿一个真实例子说。何爬某教育平台把课程视频切成几百个 ts 分片,取网播放列表放在 m3u8 文件里。页视你打开开发者工具的何爬 Network 面板,能看到浏览器每隔几秒请求一个 .ts 文件。取网这些请求带上了 Referer、页视User-Agent 和 Cookie,何爬缺一个就返回 403。取网所以爬视频的页视第一步不是写循环,是先把请求头伪装到位。

import requests headers = {  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Referer': 'https://example.com/course/123', } resp = requests.get(m3u8_url, headers=headers) print(resp.text) 

拿到 m3u8 内容后,你会发现里面是一行行的 ts 地址,可能还带 #EXT-X-KEY 加密标记。没加密的直接把 ts 拼起来就行。加密的得先下载 key 文件,用 AES-128 解密每个分片。这一步用 pycryptodome 库几行就能搞定,但 key 的获取地址往往又需要另一层请求头,套娃一样。

有人问为什么不直接用 you-get 或者 yt-dlp。能问出这个问题说明你还没被特定网站折磨过。通用工具覆盖的是主流平台,一旦遇到企业内部培训系统或者小众站点,还是得自己写。我上次碰到一个网站,ts 文件名是随机哈希,m3u8 里却按顺序排列,你只能老老实实解析播放列表,不能靠猜文件名批量下载。

下载环节本身不复杂,用多线程能快很多。但别开太多,20 个线程足够。我见过有人开 200 个线程把目标服务器搞挂,然后 IP 被拉黑,得不偿失。每个分片下载完写进临时文件,最后用 ffmpeg 合并:

ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4 

filelist.txt 里每行写 file 'segment_001.ts'。这样合并速度极快,因为不重新编码。

另一个坑是动态加载。有些网站的视频地址不在 HTML 里,而是通过 JavaScript 拼接出来。你直接 requests.get 页面源码,搜不到任何 m3u8 或 mp4 链接。这时候要么用 Selenium 或 Playwright 渲染页面,要么去分析 JS 里的接口调用。我倾向于后者,因为无头浏览器慢且容易被检测。打开开发者工具的 Sources 面板,给 XHR 请求打上断点,刷新页面,堆栈里就能找到拼接逻辑。

还有一类视频用 blob 协议。你在 Network 里看到的是 blob:https://...,这不是真实地址,是 MediaSource 扩展生成的。真实数据流还是通过 XHR 或 Fetch 传输的,切到 Network 的 Media 标签或者过滤 .m4s、.ts 就能找到源头。别被 blob 吓住,它只是浏览器内存里的一个引用。

最后说个现实问题。爬视频用于个人学习,和批量下载再传播,性质完全不同。前者没人管你,后者可能收到律师函。我自己的做法是只爬公开课和允许下载的素材,遇到付费内容直接放弃。技术能实现的事,不代表应该做。写代码之前先看一眼 robots.txt 和服务条款,比事后删库跑路强。

代码跑通那一刻确实爽,但维护爬虫是另一回事。网站改一次结构,你的解析逻辑就废了。所以尽量把请求头、解析规则、下载逻辑拆成独立模块,改起来不用翻整个文件。这算是我踩了无数次坑之后最实在的经验。

分享到: