提示

返回博客列表

视频地址藏在 JS 里?彻底搞懂通用流地址提取的思路与实战

视频地址藏在 JS 里?彻底搞懂通用流地址提取的思路与实战

下载器最核心的能力,就是找到真实视频地址。早些年视频多在页面里直接写个 <video src="...">,现在几乎都藏起来了:m3u8/mpd 地址在 JS 变量里、在异步接口返回的 JSON 里、甚至被加密混淆。这篇文章不针对某个具体网站(那会过期),而是把"怎么把流地址抠出来"的通用方法论讲透:从最简单的看源码,到无头浏览器、中间人代理、JS 反混淆。

一、流地址通常躲在哪些地方

  1. HTML 源码<video src="..."><source> 标签;
  2. 内联 JS 变量var playInfo = { url: "..." }
  3. 异步接口:页面加载后 JS 再请求一个 API 拿播放地址;
  4. 加密/混淆:地址被 base64、AES 或自定义算法处理;
  5. m3u8 套 m3u8:主 playlist 指向真实切片地址;
  6. WebSocket / WebTransport:不走普通 HTTP 请求。

二、方法一:先看源码 + 抓包(最低成本)

两板斧:

  • 右键"查看网页源代码",搜 m3u8mpd.mp4.tsplayUrlvideoUrl
  • 打开开发者工具 → Network,过滤 m3u8/mpd/ts/mpd,往往直接能看到请求。

很多站点其实没那么复杂,抓包就能拿到真实地址。记得带上正常的 User-Agent 和必要 Referer,否则页面可能返回空壳。

三、方法二:正则从 JS 文本里抠

地址在 JS 变量里时,把页面或 JS 文件拉下来用正则:

import re, requests

html = requests.get(url, headers={'User-Agent': 'Mozilla/5.0'}, timeout=15).text
# 匹配常见模式
for pat in [r'"(https?://[^"\' ]+\.m3u8[^"\' ]*)"',
            r'url["\': ]+(https?://[^"\']+\.mp4)',
            r'playUrl["\': ]+"([^"]+)"']:
    m = re.search(pat, html)
    if m:
        print('found:', m.group(1))
        break

注意要带 UA,且很多站点用 JSON 明文传,搜 m3u8 几乎必中。

四、方法三:无头浏览器执行 JS

当地址是 JS 动态生成、或需要登录态触发请求时,静态抓源码没用。用 Playwright/Puppeteer 真正跑一遍页面,让它把请求发出来我们再拦:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    b = p.chromium.launch(headless=True)
    pg = b.new_page()
    pg.on("request", lambda r: print(r.url) if ('.m3u8' in r.url or '.mp4' in r.url) else None)
    pg.goto(url)
    pg.wait_for_timeout(6000)   # 等页面触发请求
    b.close()

页面一发起 m3u8/mp4 请求,我们就捕获到了真实地址。还能用 pg.context.add_cookies(...) 带登录态。

五、方法四:中间人代理(mitmproxy)

对付强反爬/加密最彻底:让流量过 mitmproxy,直接看明文请求和响应:

from mitmproxy import http

def request(flow: http.HTTPFlow):
    u = flow.request.url
    if '.m3u8' in u or '.mp4' in u or 'play' in u:
        print('[REQ]', u)

def response(flow: http.HTTPFlow):
    # 看响应体里有没有地址
    if 'application/json' in flow.response.headers.get('content-type',''):
        print('[RES]', flow.response.text[:500])

启动 mitmproxy -s script.py,浏览器挂上代理(装好 mitm 证书解密 HTTPS),所有请求一览无余。配合解密 HTTPS 还能看到加密前的参数。

六、解密混淆地址

拿到的是加密串时思路:

  1. 在 JS 里搜相关变量名/函数名(如 decryptparseUrl),定位解密函数;
  2. 用 Node 把那段解密函数跑起来,把密文喂进去;
  3. 或在 Playwright 里 page.evaluate 直接调用页面自带的解密函数拿明文。

七、m3u8 嵌套处理

主 m3u8 经常只是指向清晰度列表(又一层 m3u8)。提取时要递归跟随,选目标清晰度那一层,再下切片。

八、方法对比

方法 难度 适用
看源码/抓包 地址明文
正则提取 在 HTML/JS 文本里
无头浏览器 动态生成/需登录
中间人代理 强反爬/加密

九、常见翻车现场

现象 根因 解法
抓包啥都没有 走 WebSocket/非 HTTP 看 WS 帧或换协议分析
拿到 m3u8 下不动 需带 Referer/Cookie 下载时一并传上(见 referer/cookie 用法)
地址是加密串 JS 混淆 Node 跑解密函数
播放 403 防盗链 加正确 Referer/Origin
频繁变地址 签名/时效性 Token 提取后立即用,别缓存

十、常见问题

Q:为什么有时抓到的是 .mpd 不是 m3u8? 那是 DASH 格式,用 dash 下载器(如 yt-dlp 自带)或 ffmpeg 直接读 mpd。

Q:网站经常改版怎么办? 没有一劳永逸,把提取逻辑做成可配置的"规则",哪变了改哪条规则,比写死健壮。

Q:这样做合规吗? 提取自己有权限观看的内容、做个人离线备份通常没问题;批量抓取收费/版权内容分发则另当别论,务必评估法律风险。

小结

流地址提取是"分层递进"的活:先试最便宜的看源码/抓包,不行上正则,再不行无头浏览器,最硬核上 mitmproxy。核心是理解地址藏在哪一层,然后用对应工具把它逼出来。

想亲手试试?用 VidDown 一键解析下载

粘贴视频链接即可解析,多平台支持、网页端即用;下载桌面客户端解锁海外平台本地解析,开通会员更享不限次下载。

顶部