提取网页内嵌音频真实url需五步:一查audio标签的src/data-src等属性;二正则扫描script中m3u8/mpd/json配置;三处理blob:url需selenium捕获请求;四base64直接解码;五流式下载并安全重命名。

网页内嵌音频通常不直接暴露真实文件 URL,而是通过 JavaScript 动态加载或封装在 blob / base64 / m3u8 / dash 中;直接请求 src 属性往往返回 403、重定向失败或空响应。必须先提取真实音频地址,再流式下载并安全重命名。
怎么从网页 HTML 或 JS 中提取真实音频 URL
多数音频由 <audio></audio> 标签的 src 属性提供,但有些网站会把地址藏在 data-src、data-url 或内联 <script></script> 里(如 JSON 配置对象)。遇到 m3u8 或 mpd,说明是分片流媒体,不能直接当普通文件下载。
- 用
requests获取页面 HTML 后,优先查audio标签所有src、data-src、data-audio-url属性值 - 若没找到,用
re.search(r'["']([^"']*.m3u8?[^"']*)["']', html_text)扫描 script 内容,注意转义和引号匹配 - 遇到
blob:开头的 URL(如blob:https://example.com/abc123),说明音频由 JS 创建,需用 Selenium 或 Playwright 模拟运行,再从window.URL.createObjectURL调用栈中捕获真实请求 - 若返回的是 base64 字符串(
data:audio/mpeg;base64,...),直接用base64.b64decode()解码保存,无需流式
如何用 requests 流式下载并避免内存爆炸
音频文件可能上百 MB,一次性 response.content 会吃光内存。必须用 stream=True + 分块写入,同时手动处理重定向和 cookie。
仅使用 Python 将 Claw Code 虚拟化框架与 OpenClaw 集成,提供 184 种工具和 200 多条命令,用于安全分析和代码质量...
- 始终设置
stream=True:否则response.iter_content()不可用 - 检查
response.is_redirect或response.history,确认最终 URL 是否含签名参数(如?Expires=123&Signature=xyz),这类链接有时效性,不可缓存复用 - 用
response.headers.get('content-length')预估大小,但某些 CDN(如 Cloudflare)会省略该 header,此时跳过进度计算 - 写入时用二进制模式打开文件:
open(filename, 'wb'),每块大小建议8192(即 8KB),太小增加 I/O 次数,太大无实质收益
import requests
r = requests.get(audio_url, stream=True, headers={'User-Agent': 'Mozilla/5.0'})
with open('output.mp3', 'wb') as f:
for chunk in r.iter_content(8192):
if chunk:
f.write(chunk)
怎么安全地重命名下载文件(避免路径遍历与非法字符)
网页给的 filename 可能含 ../、控制字符或 Windows 不允许的 |?*,直接拼接路径会导致覆盖系统文件或写入失败。
- 不要信任
Content-Disposition中的filename=,优先用自己生成的名称(如基于 URL path 或标题哈希) - 用
urllib.parse.unquote()解码 URL 编码,再用re.sub(r'[\/*?|"]', '_', name)替换非法字符 - 禁止解析出的路径含
..或绝对路径前缀(如/etc/passwd),用os.path.basename()强制取文件名部分 - 扩展名必须显式指定(如
.mp3),不能依赖 URL 后缀——有些音频 URL 是/play?id=123,实际内容却是 AAC
真正麻烦的永远不是下载本身,而是 URL 怎么来、有效期多长、是否要带 Referer 或 token、以及重命名时要不要保留原始语义(比如 podcast 标题里的冒号得换成中文顿号)。这些细节不提前验证,跑起来才发现文件名乱码或下了一半 403,就只能回退补逻辑了。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










