音频链接藏在network面板中,而非网页源码;需播放音频后筛选media请求,注意xhr返回的加密路径、防盗链header、token时效性及mime类型映射。

音频链接藏在哪?先看网页源码还是 Network 面板
PHP 爬虫抓不到音频,大概率不是代码写错了,而是根本没找对链接位置。很多网站把 audio 标签的 src 属性设为 JS 动态生成的地址,或者用 Blob URL、分片加载(如 HLS/DASH),直接扒 HTML 源码只会看到空值或占位符。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 打开浏览器开发者工具 → 切到 Network 面板 → 播放音频 → 筛选
media或mp3/wav/m4a类型请求,真实下载地址就在这里 - 若看到
XHR或fetch请求返回 JSON,里面可能含加密后的音频路径或 token,得先模拟登录/带 Header 请求 - 禁用 JS 后刷新页面,如果音频消失或
src变成空,说明依赖前端渲染,PHP 直接 cURL HTML 就无效
file_get_contents() 和 curl_init() 抓音频文件的区别
file_get_contents() 看似简单,但默认不支持设置 Referer、User-Agent,遇到防盗链(403 Forbidden)或反爬校验基本失败;而 curl_init() 可控性强,但容易忽略二进制流处理细节。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 必须显式设置
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true),否则音频文件可能被截断或乱码 - 加上
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true)处理 302 跳转——很多音频 CDN 地址是临时签权 URL,不跟跳就 404 - 别用
file_get_contents()直接写文件,它会把二进制当字符串处理;改用fopen()+fpassthru()或file_put_contents($path, $content, LOCK_EX)
防盗链(Referer)、Token、User-Agent 怎么模拟才不被拦
音频资源常比图文更严防盗链,仅靠伪造 User-Agent 不够,Referer 缺失、时间戳过期、sign 签名错误都会导致 403 或返回空文件。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- Referer 必须和来源页面 URL 完全一致(包括末尾斜杠、协议),比如来源页是
https://example.com/play?id=123,Referer 就得设成这个,不能只写域名 - 有些接口要求
X-Requested-With: XMLHttpRequest或Accept: audio/*,漏掉就返回 HTML 页面而非音频流 - 若 URL 中含
token=xxx或t=171xxxxxx,注意该时间戳是否是秒级/毫秒级,PHP 用time()还是round(microtime(true) * 1000)得看目标接口文档(没有文档就抓包对比)
保存音频文件时文件名乱码、后缀错、大小为 0 的原因
PHP 默认不解析响应头里的 Content-Disposition,也不自动推断音频类型,靠扩展名硬写 .mp3 很容易错——比如实际是 audio/mpeg 却返回 audio/mp4,或服务器返回的是 octet-stream。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 用
curl_getinfo($ch, CURLINFO_CONTENT_TYPE)拿到真实 MIME 类型,映射成后缀:audio/mpeg → .mp3,audio/mp4 → .m4a,audio/wav → .wav - 保存前检查
curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD),若为 0,说明请求失败但没报错(比如 403 返回了 0 字节),需提前拦截 - 中文文件名别直接拼进路径,用
mb_convert_encoding($name, 'ISO-8859-1', 'UTF-8')转码,或干脆用 ID 命名 + 数据库存原始名
音频链接往往裹着多层逻辑:JS 渲染、动态 token、Referer 校验、MIME 类型伪装。光会发请求没用,得盯着 Network 面板里那个真实下载请求,把它完整复现出来——少一个 Header,或时间戳差一秒,文件就废了。











