ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

m3u8视频下载实战:抓地址、合并切片与防盗链处理

m3u8视频下载实战:抓地址、合并切片与防盗链处理 网页视频下载这事看着简单真做起来全是坑。很多朋友一上来就按F12在Network里翻半天以为能找到一个现成MP4地址结果发现整个页面加载了几百个请求媒体文件反而像捉迷藏一样找不到。这篇是这个系列的第3篇案例我拿一个比较有代表性的场景展开网页里通过m3u8分段加载的视频怎么完整下载到本地包括抓地址、合并切片、绕防盗链、处理加密和音视频分离。适合已经会用一点开发者工具、但经常被“403”“奇怪的ts文件”劝退的朋友。看完之后八成常见的网页视频下载需求你都能自己搞定。1. 这个案例和前面两篇有什么不一样1.1 为什么不能右键另存为早期很多视频网站为了省事直接把MP4文件放在网页里浏览器拿到地址后右键另存或者从开发者工具找到MP4路径就能下载这也是网上大部分“网页视频下载教程”的适用范围。但现在主流站点基本都换了流媒体播放视频不再是一个完整文件而是被切成几秒一段的小视频块播放器播完一段再去拉下一段所以你在Network里看到的往往是一堆不断跳出来的小文件而不是一个MP4。这个过程有点像自助餐不是一次性给你端一桌菜而是后厨按顺序一道道上你只能吃到当前这道想打包全集就得拿到那张“菜单”。流媒体里的菜单就叫m3u8它是一份纯文本清单记录着每个小视频块的地址和播放顺序。只要把这份菜单抓到再按顺序把所有分片合在一起就能还原出完整视频。这个案例的核心思路就四个字先拿菜单再拼文件。1.2 m3u8到底是个什么东西m3u8的严格叫法是HLS播放列表最早是苹果提出的HTTP Live Streaming标准现在基本成了网页点播和直播的通用格式。它本质上是个UTF-8文本文件你可以用记事本打开。一份最简单的点播m3u8长这样#EXTM3U #EXT-X-VERSION:3 #EXT-X-TARGETDURATION:10 #EXTINF:10.000000, segment_0.ts #EXTINF:10.000000, segment_1.ts #EXT-X-ENDLIST以#开头的是指令#EXTINF后面跟着分片时长和文件名播放器就按这个顺序把segment_0.ts、segment_1.ts依次拉出来播放。如果文件里的地址是相对路径需要跟你刚才拿到的m3u8地址做拼接。你还会看到#EXT-X-KEY这样的指令那是告诉播放器“后面的分片被加密了用这个密钥解”这个后面详细讲。还有一个判断点#EXT-X-ENDLIST出现基本说明这是点播视频也就是已经录制好、不会变长的内容适合下载如果始终没有ENDLIST那多半是直播流这种方法只能拉到一个时间窗口的画面意义不大。所以拿到m3u8先别急着下载花十秒看一眼内容后面能省很多事。1.3 动手前先准备好这几样工具做这个案例我习惯用到三样东西浏览器开发者工具、FFmpeg、还有一个能发自定义请求的命令行工具。浏览器开发者工具用来抓地址FFmpeg用来下载和合并curl或者wget用来排查请求头。FFmpeg是命令行工具功能很强大相当于视频界的瑞士军刀。Windows用户可以去官网下载解压包把bin目录配置到环境变量macOS可以用brew install ffmpegLinux发行版一般也有官方源apt install ffmpeg或者yum install ffmpeg都行。装好后打开终端敲一句 ffmpeg -version能正常输出版本号就算成了。这类工具不需要学得很深你会用 -i 指定输入、-c copy 直接复制流、-t 剪时长基本就够应付大多数网页视频下载场景了。实在不想装命令行也可以找现成的m3u8下载器但我还是建议至少把FFmpeg跑通因为你后面排查问题、转格式、混流都会用到它一劳永逸。2. 第一步把视频地址从浏览器里揪出来2.1 抓包的三个关键动作用开发者工具找媒体地址流程可以固定成三步打开Network面板、刷新页面开始播放、盯住Media和Fetch/XHR两个过滤条件。具体操作是先按F12打开开发者工具切到Network标签勾选Preserve log保留日志然后按CtrlF5强制刷新页面让所有网络请求重新记录一遍。这时候再点播放你会在列表里看到一堆segment开头、以ts结尾的小文件恭喜那就是视频分片。在过滤框输入m3u8如果网站用HLS播放一般能直接看到列表项如果没看到再看Fetch/XHR里有没有类似playlist、index.m3u8的请求。有些网站把视频地址包在blob:https://一堆字符里src看起来是blob地址这种直接复制到下载工具里是没用的因为blob内容只存在浏览器内存中。这种情况要往回追看是哪个XHR请求返回了m3u8或者MPD真正能用的地址藏在那个响应里。如果没有看到任何媒体相关请求先确认是不是缓存问题清一次缓存再刷新如果视频来自第三方iframe比如某些平台的播放器是嵌套进来的可能请求记录在另一个文档里可以切到frame选择器去看。经验上90%的网页视频都能在Network里找到答案找不到更多是过滤条件没调对。简单提一句有些视频页面里有个标签但src是blob。这时候在Console执行 document.querySelector(video).src 拿不到原始地址但可以看video标签当前播放的时长、倍速等信息辅助你判断视频是否加载成功。2.2 打开m3u8之后怎么看找到m3u8地址后新开一个标签页直接打开通常要么下载一个文本文件要么浏览器直接展示文本内容。先别管那些堆成山的分片地址重点看几个指令。第一如果内容里只有一行子播放列表地址比如一个叫index.m3u8的入口文件指向了quality_720p.m3u8那说明这是多码率主列表还需要再打开子列表才是真正要下载的清单。第二看有没有#EXT-X-KEY有的话说明分片是加密的后面需要带上密钥信息。第三看是点播还是直播有没有#EXT-X-ENDLIST这个刚才说过了。可能有人问地址拿到了直接复制到下载软件里不就行了吗如果是公开地址确实可以但很多网站会给地址加上防盗链。你用浏览器访问没问题因为浏览器自动带上了正确的Referer、User-Agent、Cookie。脱离浏览器环境直接请求服务器一看来源不对直接回一个403。所以只找到地址不算完还要把请求头一起带走这一步是这个案例里最实战的部分。2.3 顺手处理快进、全屏暂停、禁止拖动调试视频的时候有几个小技巧很实用。想在网页里快速定位视频内容别再手动拖进度条了直接在Console执行document.querySelector(video).currentTime 60;这句代码会把当前播放位置往后跳60秒想跳多久改数字就行。想倍速播放就执行 video.playbackRate 2。这种操作对下载也有用比如你想确认视频中间某个片段是否正常加载可以先把进度跳过去再看Network请求。至于“网页视频被其他全屏后暂停播放”多半是播放器监听了fullscreenchange事件主动调用了暂停或者全屏切换导致焦点变化在Console里临时给video对象挂一个play回调可以缓解。有网站会禁止拖动进度条本质上是监听dragstart之类的鼠标事件然后阻止默认行为。你可以在Console里临时把这些事件处理函数置空或者直接用播放器自带的键盘快捷键。不过要记住这些操作都只是前端临时改动刷新页面就恢复。它们解决的是“看视频不方便”的问题而不是“下载视频”的问题别指望靠这点操作绕过所有限制。3. 第二步用FFmpeg把切片拼成完整视频3.1 一条命令搞定基本下载拿到m3u8地址并且确认没有网络限制之后最简单的下载命令是ffmpeg -i https://example.com/path/index.m3u8 -c copy output.mp4FFmpeg会自动读取m3u8列表把里面的所有ts分片下载下来然后按顺序封装成output.mp4。-c copy的意思是视频和音频流都不重新编码直接拷贝进新容器。这么做的最大好处是速度快几个小时的长视频拷贝模式下几分钟到十几分钟就能完成而且画质无损。如果-c copy失败比如输出格式不支持某些编码才考虑去掉-c copy用libx264重新编码但转码非常耗时属于最后手段。我在实际操作中基本都会把视频地址用英文双引号包起来因为很多m3u8地址里带和?参数不加引号命令行会拆出问题。分片数量特别多的时候FFmpeg可能会因为某个切片超时卡住可以加上网络超时参数比如-rw_timeout 10000000表示网络读取超时上限10秒。如果还是经常断优先考虑网络原因降低并发、多试几次或者找一个更稳定的网络环境。有些m3u8清单里分片数量能到几百上千个FFmpeg默认是串行下载耐心等就是。3.2 防盗链处理把浏览器的请求头还回去第3篇案例要重点强调的事来了大多数下载失败不是命令写错而是没有把请求头补全。浏览器访问一串m3u8时服务器会校验来源页面、UA、登录Cookie。命令行工具访问的时候这些信息全都没有于是服务器回了403。解决的思路很简单把浏览器里那个m3u8请求的请求头原样搬过来。最省事的做法是在Network里找到那个m3u8请求右键选择Copy as cURL这样会复制出一条完整curl命令里面带好了所有请求头。你可以在终端里先跑一下这条curl正常能拿到内容再把里面的-H参数转成FFmpeg能用的形式。比如ffmpeg -headers Referer: https://example.com/page/123 -headers User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) -i https://example.com/path/index.m3u8 -c copy output.mp4如果网站需要登录还得把Cookie加进去同样是复制浏览器里的值。这里有个细节很多平台给m3u8和分片地址签了时效token地址后面会带一串expire和sign参数这种链接可能过几分钟就失效。所以最佳节奏是抓到一个可用地址后马上复制请求头立刻开始下载别等研究完再去不然又是一堆新的403。真遇到失效重新刷新页面再抓一次就好。3.3 加密切片和音视频分离怎么办m3u8里有#EXT-X-KEY指令说明分片是AES-128加密的。FFmpeg对这个情况的处理比较智能它看到KEY里的URI后会自动去请求密钥文件然后用密钥解密每个分片。前提是密钥文件地址能正常访问。如果密钥请求也403那还是防盗链问题通常FFmpeg在请求密钥时会沿用m3u8的请求头设置所以携带Referer和User-Agent后一般就能解决。万一遇到个别站点对密钥请求单独校验可以先把密钥文件通过浏览器下载下来再用其他工具手动解密不过这种情况很少见先不用学那么深。另一个更常见的问题是音视频分离。很多自适应码率的站点会把视频画面和音频分成两个不同的m3u8播放器分别拉取再同步播放。一个典型现象就是FFmpeg下载完文件播放只有画面没有声音。解决办法是在Network里多找一条涉及audio、sound、m4s之类关键词的m3u8分别下载成两个文件再用FFmpeg合并ffmpeg -i video.mp4 -i audio.m4a -c copy combined.mp4判断有没有音视频分离的方法很简单看m3u8主列表内容如果里面包含多行带RESOLUTION和CODECS属性的条目并且某些行里音频相关信息和视频不同那就是多路流。这种时候与其硬用一条命令下载不如先把视频流和音频流分开抓再合并成功率会高很多。4. 常见问题与排错实录4.1 最常见的四类报错对照这个案例做多了常见错误就那么几类整理成表格报错现象大概率原因解决思路403 Forbidden防盗链或签名过期补全Referer、User-Agent、Cookie重新抓取新地址404 Not Found地址拼接错误或切片过期去m3u8里核对相对路径刷新页面重新抓包解析m3u8失败/不支持标签m3u8格式特殊或文件损坏换一个下载器或用文本打开检查是否完整连接超时/中途卡住网络不稳或分片并发过高加超时参数、减少并发、重新执行下载403是出现频率最高的一种你只要记住它不代表“不能下载”只代表你的请求不被认可把浏览器的请求头原样带过去多数情况下就能通过。404里有个容易被忽略的点m3u8文件里写的分片路径是相对路径你自己拼URL时一旦拼错FFmpeg就会找不到文件。好消息是大多数FFmpeg版本会自动拼接相对路径但如果你手动改过地址就要注意。连接超时在高码率视频里也常见分段太多加上网络波动就会下到一半卡住。我的习惯是先重试一次如果还卡就用专门的下载器或者降低视频清晰度别跟一条地址死磕。4.2 下载完打不开、没有声音、音画不同步下载完成的文件如果打不开先看看文件后缀和实际封装格式是否匹配。FFmpeg输出时如果写的是MP4但源流里有某些不被支持的编码文件播放可能会有问题。遇到这种情况我一般会把输出格式改成MKV再试ffmpeg -i input.ts -c copy output.mkvMKV的兼容性很好对各类编码流基本都能装。如果播放器还是不认再考虑用ffprobe看一下编码信息ffprobe是FFmpeg自带的检测工具执行ffprobe -show_streams output.mkv就能看到画面和音频用的什么编码。没有声音的问题刚才说了优先去查音视频是否分离。音画不同步多发生在下载过程中网络抖动导致某些分片损坏稳妥的办法是删除文件重新下载不要在残缺文件上反复折腾。也有极少数情况是切片本身时间戳混乱用ffmpeg -fflags genpts可以重新生成时间戳但效果不保证。4.3 右键被禁、控制台被卡怎么破有些网站为了防小白会禁止右键甚至打开F12后不断进入debugger暂停。这些基本都是前端小把戏。右键禁用不影响F12快捷键你一样可以打开开发者工具。遇到debugger反复暂停在Sources面板里按CtrlF8停用所有断点就能正常操作。如果你发现Network里明明在播放视频却看不到媒体请求优先怀疑缓存开一个无痕窗口再抓往往就有结果了。还有一种情况是视频用iframe嵌套请求记录不在主文档里。开发者工具里有一个frame选择下拉框切换到视频所在的那个frameNetwork记录就会显示对应子文档的请求。这个点卡住了不少新手我特意在这里写出来希望你能少绕点路。记住一个原则所有前端限制都只能增加操作成本不能真正保护视频因为播放视频终究要把数据传到浏览器端。真正的下载限制靠的是服务端鉴权和加密这也是我们要去看请求头和m3u8内容的原因。5. 进阶玩法批量下载和自动化5.1 用脚本批量下载整季课程如果只是下一两个视频手动操作就够了。但你可能会遇到一个系列有几十集的情况这时候逐个复制地址再执行命令效率太低了。如果分页URL或者m3u8地址有规律可以直接写一个循环脚本。比如某个课程的地址规律是/course/lesson01/index.m3u8到/course/lesson20/index.m3u8那么在bash里这样写#!/bin/bash basehttps://example.com/course/lesson for i in $(seq -w 1 20) do ffmpeg -headers Referer: https://example.com \ -i ${base}${i}/index.m3u8 \ -c copy lesson_${i}.mp4 doneseq -w会把数字补成01、02这样的两位格式方便对齐文件名。跑之前一定要先单集验证一遍确认请求头、地址规律都没错再开批量。批量下载时建议在循环里加一句sleep 3避免短时间请求太频繁被站点限流。这行里有一句话叫“下载五分钟封IP两小时”虽然这个案例一般不会到封IP的程度但尊重对方服务器的压力总没错。5.2 Python辅助脚本怎么个思路有些场景用bash不太合适比如地址需要通过Post请求接口获取、需要先登录拿token、或者文件名要从页面标题里提取这时候用Python脚本更顺手。核心逻辑不复杂用requests请求接口拿到m3u8地址再交给FFmpeg子进程下载或者自己解析m3u8后逐个下载分片再合并。直接贴一段可跑的代码没意义因为不同平台的接口完全不一样但思路是一致的1. 模拟登录或者直接复用浏览器Cookie 2. 解析出视频页面里的m3u8接口地址 3. 请求接口拿到最终m3u8 4. 调用FFmpeg下载并合并复用浏览器Cookie的方式很简单从开发者工具里任意请求的请求头里复制Cookie字段粘贴到脚本的headers里就能在脚本里模拟登录态。这个做法对付需要登录验证的站点时非常管用。整个脚本体量通常在一百行以内比纯手动操作省心得多。当然如果你对命令行更熟直接复制curl命令也能达到同样效果。工具只是手段核心是对请求流程的理解。6. 处理案例时我的几个固定习惯我自己做这类下载案例的时间越长越觉得最重要的不是记命令而是会看协议。m3u8看得懂、请求头补得齐、加密和音视频分离遇到时能有应对方向任何网页视频到手里都只是时间问题。我自己的固定习惯是先花十秒看m3u8内容再决定下一步而不是拿到链接就盲跑命令遇到403先补头遇到怪异文件先查分片列表基本能解决九成问题。最后再分享一个小技巧下载前先想清楚自己是不是真的有权限获取这个内容。工具本身是中立的但用在哪、怎么用决定了很多事情。学习自用是一码事拿别人的版权内容去传播或者商用就是另一码事。把技术用在合法合规的事上你才能安心地一直玩下去。
返回列表