简介:面向被百度网盘下载速度和客户端限制困扰的普通用户,也适合对浏览器自动化脚本感兴趣的前端学习者,这份 .user.js 脚本可配合 Tampermonkey 或 Greasemonkey 运行,解析网页版请求并提取真实直链,自动触发浏览器原生下载。压缩包解压后仅含 1 个 js 文件,大小约 15KB,基于浏览器 JavaScript 环境编写,功能链路完整,涵盖请求监听、参数解析、直链拼接、下载启动等逻辑,便于快速投入使用或二次修改。该资源已有 10489 人学习/下载,关注度较高,说明同类需求群体较大。获取后既能直接部署使用,也能作为用户脚本开发的小型范例,掌握 DOM 分析、HTTP 请求捕获、Cookie 传递等技术细节,了解脚本执行流程与常见安全风险;同时需注意脚本权限与百度网盘服务条款,确保账号安全和合规使用。
1. 百度网盘直链下载,一个 user.js 脚本就够:先看它解决了什么
百度网盘几乎成了国内资源共享的默认入口,但“百度网盘下载”这件事长期停留在“能下,但难受”的阶段:官方客户端不向你暴露真实的直链,网页版下载大文件容易断线,尤其当对方发来的是一个纯分享链接,点击“下载”之后要么唤起客户端,要么让你重复登录。折腾过一圈的人,最后大多会回到同一个办法——用一个叫“百度网盘直接下载助手”的 user.js 脚本。它的作用简单说就是:在百度网盘分享页面上读取当前的签名信息,调用百度网盘自己的一套下载接口,换取一条带时效的百度网盘直链,然后把这条直链交给下载工具去跑。这篇文章就从这条“从分享页到直链”的路径说起,讲清楚它的原理、安装方法、参数设置,以及最常见的几个坑。
适合谁读:想从群里、论坛里那些“链接+提取码”的资源帖里快速拿文件的人;维护油猴脚本、想模仿这类工具做法的开发者;以及被“网页下载到一半就断线、点重试又要重新登录”折磨到没脾气的人。读完你至少能判断这条方案值不值得投入,也能知道自己改脚本时该从哪里下手。
2. 直链不是黑魔法:user.js 怎样从分享页换到百度网盘直链
先拆一个结论:所谓“百度网盘直链”,并不是脚本自己在服务器上造出来的私有地址,而是百度网盘服务端本来就有的下载地址。只是这个地址平时只出现在客户端流程内部,或者藏在特定接口返回的 JSON 里。用户脚本做的事情,是把网页里那些跳转、弹窗、唤起客户端的中间步骤全部过滤掉,直接拿到最终的 dlink 字段,再展示给你。
这一章我不打算粘贴某个具体仓库的完整源码,而是写一个最小可用的 user.js 骨架。等你理解了骨架,再去看网上下载的“百度网盘直接下载助手”,就不会觉得它是黑匣子,反而能判断它到底靠不靠谱。
2.1 脚本在分享页里做了什么:先看懂 sign、timestamp、randsk
百度网盘的分享下载链路大致是这样:你打开一个pan.baidu.com/s/xxx分享链接,页面会先请求/share/init这个初始化接口,返回一堆参数。里面最关键的是sign、timestamp、randsk、uk、shareid这几个。你可以把它们理解成一次访问的门票:sign是签名,timestamp是时间戳,randsk是随机凭证,用来标识“当前这个浏览器会话对这次分享有合法访问权限”。
拿到这些参数之后,页面上的“下载”按钮才会生效。点击下载时,前端会带着这些参数去请求另一个接口/api/sharedownload,服务端校验通过后,返回一个文件列表,列表里每一项都有dlink字段。这个dlink就是你要的直链。
user.js 的介入点就在这里。脚本监听页面上/share/init的响应,把sign、timestamp、randsk、uk、shareid存到内存里;然后在页面角落生成一个“生成直链”按钮。当你点击按钮,脚本用同样的参数发一次/api/sharedownload请求,这一步等价于你在网页上亲手点了一次下载,只是脚本把返回的直链以文本方式展示出来,还顺手复制到了剪贴板。
为什么非要走这个接口,而不直接抓网页上那个“下载”按钮的最终地址?因为网页上的下载按钮往往要先唤起客户端,或者在点击后才动态拼出地址。你从 DOM 里看到的地址是带一堆转义符号的中间页,不是最终文件流地址。脚本帮你绕开这些中间逻辑,直接走到接口最后一步,拿到的才是干净直链。
2.2 最小可用的 user.js 骨架:元数据块、请求函数与落地页
下面是一个最小可用的用户脚本骨架,逻辑完全贴近“百度网盘直接下载助手”的思路,但刻意做成了演示版本,不保证直接适配当前所有页面。它的价值在于把最关键的三段逻辑写清楚了:脚本声明、初始化参数占位、换取直链的请求函数。
// ==UserScript== // @name 百度网盘直链提取参考骨架 // @version 0.1 // @description 演示在百度网盘分享页用共享接口换取直链的思路,非完整助手 // @match *://pan.baidu.com/share/init* // @match *://pan.baidu.com/s/* // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @run-at document-idle // ==/UserScript== (function () { 'use strict'; const state = { sign: '', timestamp: '', randsk: '', uk: '', shareid: '', fsId: '' }; async function fetchRealLink() { const surl = location.pathname.split('/s/')[1]; const api = '/api/sharedownload?sign=' + encodeURIComponent(state.sign) + '×tamp=' + encodeURIComponent(state.timestamp) + '&randsk=' + encodeURIComponent(state.randsk) + '&surl=' + encodeURIComponent(surl); const params = new URLSearchParams(); params.set('encrypt', '0'); params.set('product', 'share'); params.set('uk', state.uk); params.set('shareid', state.shareid); params.set('primaryid', state.fsId); params.set('type', 'nolimit'); params.set('t', Date.now()); const res = await GM_xmlhttpRequest({ method: 'POST', url: api, data: params.toString(), headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' }, responseType: 'json' }).catch((err) => { console.error('直链请求失败', err); return null; }); const item = res && res.response && res.response.list && res.response.list[0]; if (item && item.dlink) { GM_setClipboard(item.dlink, () => alert('直链已复制,请尽快开始下载')); } else { alert('未取到直链,请查看控制台日志'); } } function injectButton() { const btn = document.createElement('button'); btn.id = 'my-dlink-btn'; btn.textContent = '生成直链'; btn.style.position = 'fixed'; btn.style.right = '20px'; btn.style.bottom = '80px'; btn.style.zIndex = 9999; btn.addEventListener('click', fetchRealLink); document.body.appendChild(btn); } function waitInitData() { // 实际实现需要 hook 页面的 XHR/fetch,读取 /share/init 的响应 // 这里保留占位逻辑,真实脚本会把 JSON 里对应字段填入 state console.warn('需要把 /share/init 的响应字段写入 state'); } injectButton(); waitInitData(); })();这个骨架的元数据块里,@match限制了脚本只在百度网盘分享页的两类地址上运行:/share/init和/s/*。没写https://前缀,是为了避免用户把www.域名和裸域名混在一起导致脚本失效。@grant声明了脚本要使用 GM_xmlhttpRequest 发跨域请求,以及 GM_setClipboard 写剪贴板。完整版的助手通常还会声明@connect pan.baidu.com,让油猴允许脚本主动请求该域名的接口。
fetchRealLink 函数是核心。它把sign、timestamp、randsk拼到地址栏参数上,再通过 POST 提交uk、shareid、primaryid。其中primaryid是文件列表里某个文件的 fsId。骨架里只取了list[0],也就是第一个文件;完整脚本会遍历整个list数组,逐个生成直链。type=nolimit表示不限制下载类型,这是很多网盘接口约定俗成的参数,漏了它会导致一部分文件返回 403 或空列表。
注入按钮那几行用了position: fixed,避免页面滚动后按钮跑到可视区外面。zIndex设成 9999,防止被分享页自带的弹窗盖住。真实脚本里按钮样式一般会更精致,但核心逻辑不变。waitInitData 在真实脚本里通常会 hook 页面的 XHR 或 fetch,从初始化接口的响应里提取字段;新手可以直接在浏览器控制台里手动执行一次fetch('/share/init'),把返回的 JSON 填进 state,再点按钮测试,这样调试起来比盲改脚本快得多。
2.3 拿到的是临时 URL:dlink 为什么不永久有效
很多人第一次复制出直链,直接粘贴到地址栏打开,第二天再点就说链接失效,于是以为脚本坏了。其实百度网盘直链不是静态资源地址,而是一个带签名、带过期时间的临时 URL。典型形态类似这样:
https://d.pcs.baidu.com/file/xxx?sign=...&fid=...&time=...&rt=sh&sign=...这类地址通常会绑定三样东西:访问来源 IP 段、User-Agent、过期时间戳。同一个链接,昨天能用,今天换了网络环境就返回 404;同一台机器,浏览器里没登录百度账号就生成的直链,也可能因携带的 Cookie 不完整,下载到一半被断开。
理解了这一点,就不该把直链存进收藏夹,也不该生成完放半小时再去下载。正确做法是:打开脚本按钮,生成直链,立刻交给下载工具。如果你分享的文件比较多,更要批量生成完马上批量导入,不要拖。
3. 从安装到出链:在浏览器里跑百度网盘直链下载助手的完整操作
这一章讲实际操作。虽然网上的脚本版本五花八门,但只要掌握一套固定的安装和调参流程,几乎不会出大问题。
3.1 用 Tampermonkey 跑 .user.js 文件的最小配置
先确认浏览器和脚本管理扩展。Chrome、Edge 上装 Tampermonkey,Firefox 上装 Greasemonkey 或 Tampermonkey 都可以。脚本文件的后缀是.user.js,当浏览器打开这个文件时,Tampermonkey 会识别脚本格式并弹出安装页。没弹出的话,可以手动新建脚本,把整个文件内容粘贴进去,保存,再打开百度网盘分享页看有没有按钮出现。
安装后有几个高频问题要提前处理:
- 新版 Chrome、Edge 安装油猴之后,需要进入扩展管理页,打开“开发者模式”。不打开的话,油猴菜单里的调试入口不完整,GM_setClipboard 这类能力也容易报错。
- 安装完脚本要在油猴面板里确认它处于启用状态。还要检查
@match写的域名是不是你实际访问的域名。百度网盘访问时会跳到www.前缀,如果你访问的是pan.baidu.com,脚本里写的是*://pan.baidu.com/*,通常没问题;遇到怪域名就手动放宽到*://*.baidu.com/*试一次。 - 如果分享页是 HTTPS,脚本里却出现了 HTTP 地址,浏览器会拦截混合内容。遇到点不了按钮的情况,右键地址栏左侧小锁图标,把“不安全内容”改成“允许”,再点一次按钮。这个方法只用于调试,不建议长期开,日常用还是以生成 HTTPS 开头的 dlink 为主。
我一般建议用 Chrome 做日常调试,控制台对网络请求的展示更清晰,报错信息也更详细。Firefox 的隐私设置有时会禁用第三方 Cookie,导致分享页初始化请求拿不到完整凭证,遇到脚本“时而灵时而不灵”时先检查这里。
3.2 脚本选项里值得调的三个开关:UA 覆盖、文件名修正、批量间隔
网上的“百度网盘直接下载助手”版本很多,常见功能集中在三块。下面按重要程度讲。
第一是 User-Agent 覆盖。直链地址要求请求头里的 User-Agent 匹配生成它时的值,不匹配就返回 403。完整脚本一般会默认把 UA 设置为浏览器自带值,并在设置里留一个输入框,方便你用下载工具时把 UA 同步过去。如果你发现 IDM 下载时一直报“服务器拒绝连接”,优先去 IDM 的“下载 / 高级 / 请求头”里改 UA,改成脚本配置里写的那串。
第二是文件名修正。直链 URL 里的文件名参数是 URL 编码的,直接另存会得到%E6%9F%90%E6%9F%90这种乱码。脚本应自动从接口返回的server_filename字段取中文名,替换掉 URL 里的编码参数。界面上体现为两个按钮:“复制直链”和“复制文件名+直链”。优先用后一个,尤其当文件是教程、PPT、压缩包时,文件名错了特别难收拾。
第三是批量生成间隔。分享文件夹时,脚本通常提供“全部选择”和“逐条生成”。不要一次性选中几百个文件然后点一键生成,这会让接口限流,轻则返回“操作频繁”,重则让账号短时间被风控。合理做法是每 10 到 20 条一组,间隔 600 毫秒以上,再试下一组。也可以把脚本里那个sleep(ms)函数预留出来,手动设成更大的值,稳一点。
3.3 把直链交给 IDM 或 aria2:接住链接并不代表下载成功
拿到直链之后,最常见的两个下载工具是 IDM 和 aria2。我一般先用 aria2 跑一条链接,因为它能直接显示请求头和响应状态,出了问题最容易定位。下面这段是 aria2 下载百度网盘直链的常用命令:
# 示例:用 aria2c 下载百度网盘直链,2 个线程,开启断点续传 aria2c --dir=/data/download \ --file-allocation=none \ --max-connection-per-server=2 \ --split=2 \ --min-split-size=1M \ --continue=true \ "https://d.pcs.baidu.com/file/xxx?sign=..."命令里的--continue=true对应断点续传。直链在有效期内支持 Range 请求,所以下载到一半可以原样重跑,它会从断点继续而不是从头开始。--max-connection-per-server=2是保守并发数,改到 8 或 16 并不会让速度线性提升,反而更容易触发服务端限流。--file-allocation=none避免下载前分配大文件时卡住机械硬盘。
用 IDM 的话,注意在“选项 / 下载 / 高级”里把默认连接数从 8 调低到 2 或 4,并勾选“允许继续下载”。IDM 会抓取浏览器里的新下载事件,所以脚本点复制直链之后,IDM 通常会弹出新建任务窗口,直接确定即可。如果看到文件名后缀变成.crdownload或.part,那是下载未完成的标记,不用手动删,下载完成自动消失。
还有一点值得养成习惯:直链签名里绑定了当前出口 IP。下载中途断网重连换 IP 后,原链接可能失效,此时不要反复按“重试”,回到分享页重新生成一条直链,再交给下载工具,这样速度反而最快。
4. 避坑:处理百度网盘直链下载的 5 个典型问题
这一章是踩坑实录。下面每个问题都按“现象、原因、解决”来写。遇到类似状况时不要先怀疑脚本坏了,按顺序排查,大部分问题五分钟内能定位。
4.1 现象:点复制直链后,下载下来的是几十 KB 的 .html 文件
这是新手最容易遇到的问题。直链地址本身没错,错在把它交给了浏览器内置下载器。浏览器下载器发请求时不会带上脚本生成直链时的 User-Agent 和 Cookie,服务端判断头不对,返回一个提示页,浏览器就把这个提示页当成文件保存下来,大小通常只有几 KB 到几十 KB。
原因就是直链不是一个纯静态地址,而是对请求头敏感的临时授权地址。你单独把链接发给别人,对方没有对应的 UA 和 Cookie,自然只能收到 html。
解决方式有三种:把直链交给 IDM、aria2 这类支持自定义请求头的工具;或者使用脚本提供的“复制 curl 命令”功能,把请求头一起复制走;再或者用无痕窗口重新打开分享页并登录百度账号,生成新直链后立刻下载。日常我倾向于第二种,因为 curl 命令可以贴到任意环境里跑,不依赖下载工具配置。
4.2 现象:下载下来的文件名是乱码,或者带一大串参数
原因在于直链 URL 里的文件名字段是 URL 编码后的结果。比如%E6%9F%90%E6%9F%90其实是中文“某某”的编码,而下载工具直接把它当成了文件名,并不会自动还原。还有一种情况是文件名后面跟着&sign=xxx&time=xxx,下载工具把整个字符串当成文件名的一部分。
解决:手动从脚本返回的server_filename字段里复制正确文件名,替换掉乱码。如果文件数量多,就用脚本提供“复制文件名+直链”的模式,它会在每行地址前用out=参数注明真实文件名。aria2 也支持从响应头里解析文件名,命令里补一个--content-disposition-default-utf8=true,大多数情况下能自动得到原始文件名。
4.3 现象:直链生成成功,但下载到 90% 时断了,续传报 403
原因基本只有一个:直链的签名过期时间到了。百度网盘直链的时效从几分钟到 24 小时不等,取决于接口返回的time参数和当前账号状态。下载大文件时,如果文件超过 10GB,跨夜下载很容易踩到过期线。
解决:续传救不了签名过期的直链。aria2 遇到 403 只会停下来,不会自动换新链。我的做法是在脚本里加一段逻辑:下载任务失败时,自动回到分享页重新生成一条新直链,再替换旧链接重试。如果你不想改脚本,那就把大文件分成小段下载,或者睡前重新生成一次直链。还有一个不算好但很实用的习惯:不跨夜。不是所有数据都必须通宵下载,这个取舍值得想清楚。
4.4 现象:批量生成几十条直链后,接口返回“操作频繁”
原因很明确:网盘接口有限流。脚本如果写得不讲究,用 for 循环同步发请求,每秒钟几十个请求打过去,服务端自然会拒绝,表现为“操作频繁”或直接超时。这种情况最容易出现在你选了同一个文件夹里的全部文件时。
解决:把脚本改成带间隔的任务队列。每生成一条直链,sleep 300 到 800 毫秒;更稳妥的方案是每 5 条暂停一秒,避免瞬时请求量过高。我也会在脚本里加一个失败重试计数器,同一文件连续失败三次就停止整个队列,而不是反复无脑重试。这样既保护了账号状态,也让下载任务更快进入正轨。
4.5 现象:脚本某个版本突然失效,按钮找不到,控制台全是报错
原因就是百度网盘前端会不定期改版。脚本里写死的按钮 id、class 名失效后,querySelector 找不到节点,整个脚本就不工作了。这不是玄学,是页面结构变了。
解决:维护 user.js 时不要只留最新版。我习惯把脚本文件命名成带日期的形式,比如baidu-pan-dlink-2025.01.user.js,旧版本不可用时立刻回滚到上一个可用版本。然后打开控制台,查看当前页面的实际 DOM,重新定位按钮的位置和 id,修正后本地验证通过再更新正式版。某些脚本作者会在更新源里写明“失效日期”,看到之后就要做好准备:要么等更新,要么自己动手改。
5. 直链拿到手之后:验证、续传与长期维护
最后一步是验证直链的可用性,并建立一套能长期使用的工作习惯。这个章节不讲安装,只讲怎么确认自己拿到的直链“真的能下载”。
5.1 用 curl 快速验证直链是否可断点续传
拿到一条新直链后,不要急着开下载器,先在终端里跑两个命令,优先定位问题:
# 1. 看响应头:关注 Content-Length、Accept-Ranges、ETag curl -I -L \ -H "User-Agent: Mozilla/5.0" \ "https://d.pcs.baidu.com/file/xxx?sign=..." # 2. 用 Range 请求测试断点续传:只请求最后 1MB curl -L -r -1048576 \ -o /dev/null \ -w "%{http_code} %{size_download}\n" \ "https://d.pcs.baidu.com/file/xxx?sign=..."第一条命令看响应头里有没有Accept-Ranges: bytes,以及 Content-Length 是否是文件真实大小。如果返回 416 Range Not Satisfiable,说明服务端不认可 Range 请求,下载工具断线后只能从头开始。第二条命令用 Range 请求文件末尾 1MB,返回 206 或 200 都代表支持分片;出现 403 基本就是这个链接已经失效,或者 UA 不对。
这套验证步骤不需要每次都做。每天第一次生成直链时跑一次,之后这一天的其余链接就不用再验了。顺手把这两条命令存成一个 shell 脚本,换链接时只改参数,能在关键时刻省下不少时间。
5.2 给脚本做版本管理:日期、备份、更新源
用户脚本的代码量不大,但维护成本不低。分享页面的接口参数虽然大体稳定,前端结构却变动频繁,今天不报错的按钮也许明天就消失了。我给自己定的规则是:脚本文件必须带日期,本地保留最近三个版本,更新的同时不删除旧版。这样遇到脚本失效时,可以快速回滚到上一个已知能用的版本,而不是临时去找网盘翻车后的补丁。
配置项尽量集中在文件顶部的 config 对象里,例如批量间隔、UA、是否覆盖文件名这些开关,不要去嵌套函数里到处找散落的配置。以后百度网盘再次改版时,核心的取链函数大概率不用动,只需要适配新的页面结构,改一小段选择器就能继续用。
我这几年折腾下来最大的感受是:百度网盘直链下载这套方案并不过时,核心价值在于把下载主动权从客户端手里拿回来,让它落到你自己控制的下载工具里。但这件事依赖的细节很多,光是请求头、过期时间、批量并发就能写出一堆坑。保持脚本文件整洁、学会快速验证链接、养成不跨夜下载的习惯,这套流程就能稳稳地服务你很久。
希望这些经验能帮到你。
本文还有配套的精品资源,点击获取