nodejs实现百度网盘转存
新建文件夹并初始化
js
npm init -y安装依赖包
js
npm install axios创建config.js文件
js
module.exports = {
// 必填:把你浏览器里完整的 Cookie 字符串粘过来
cookie: '',
// 别人的分享文件地址(支持仅分享一个文件夹和多个文件夹)
url: 'https://pan.baidu.com/s/1_8lAKBYA84er6rfREjRDfw?pwd=3wuv'
};创建index.js文件
js
/**
* 百度网盘「Cookie 一键转存+再分享」
* 先验证提取码 → 再列表 → 再转存 → 再分享
* node auto_verify.js
*/
const axios = require('axios');
const { cookie, url } = require('./config');
const SHARE_URL = url; // 带提取码
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36';
const client = axios.create({
headers: { Cookie: cookie, 'User-Agent': UA, Referer: 'https://pan.baidu.com/ ' },
timeout: 15000,
});
/**********************************************************/
/* 1. 请求拦截器:打印完整报文 */
/**********************************************************/
client.interceptors.request.use(config => {
console.log('\n========== Axios 请求拦截 ==========');
console.log('url :', config.url);
console.log('method:', config.method?.toUpperCase());
// console.log('headers:', config.headers);
// URLSearchParams 会变成字符串,这里提前转一下
if (typeof config.data === 'object' && config.data.constructor.name === 'URLSearchParams') {
console.log('body :', config.data);
} else {
console.log('body :', config.data);
}
console.log('=====================================\n');
return config;
});
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
/**
* 替换 cookie 串里的 BDCLND 值
* @param {string} cookie 原 cookie 字符串
* @param {string} newVal 你要写入的新 BDCLND 值
* @returns {string} 替换后的完整 cookie 字符串
*/
function replaceBDCLND(cookie, newVal) {
const decoded = decodeURIComponent(cookie);
const replaced = decoded.replace(
/(BDCLND=)[^;]*/, // ✅ 正确正则
`$1${newVal}`
);
return replaced;
}
(async () => {
try {
/* 1. 提取码验证 → 拿 BDCLND(必须第一步) */
const surl = SHARE_URL.match(/\/s\/1([a-zA-Z0-9_-]+)/)[1];
const pwd = SHARE_URL.match(/pwd=([a-z0-9]{4})/i)[1];
const verifyRes = await client.post(
`https://pan.baidu.com/share/verify?surl= ${surl}&t=${Date.now()}`,
new URLSearchParams({ pwd: pwd, t: Date.now() }),
{ headers: { Referer: SHARE_URL } }
);
if (verifyRes.data.errno !== 0) throw new Error('提取码错误 errno=' + verifyRes.data.errno);
const sekey = verifyRes.data.randsk;
client.defaults.headers.Cookie = replaceBDCLND(client.defaults.headers.Cookie, sekey); // ✅ 添加 BDCLND 到 cookie,并去掉原有的 BDCLND
/* 2. 分享文件列表(靠 BDCLND 进验证态) */
const html = (await client.get(SHARE_URL, { headers: { Referer: SHARE_URL } })).data;
const shareid = html.match(/"shareid":(\d+)/)?.[1];
const uk = html.match(/"share_uk":"(\d+)"/)?.[1];
if (!shareid || !uk) throw new Error('未能提取 shareid 或 uk');
const bdstoken = html.match(/"bdstoken":"([a-f0-9]+)"/)?.[1];
console.log('✅ BDSTOKEN 获取成功', bdstoken);
/* 1. 定位 file_list 起始 */
console.log('✅ 获取 file_list 起始');
const chunk = html.match(/"file_list"\s*:\s*\[[\s\S]*?\]/);
if (!chunk) { console.log('file_list 数组压根没裁到'); }
else {
let str = chunk[0]
// 1. 去掉前缀 "file_list":,变成纯数组字符串
let jsonStr = str.replace(/"file_list"\s*:\s*/, '');
// 2. 解析成数组
let fileList = JSON.parse(jsonStr);
// 3. 提取 fs_id 和 path
let fsId = []
let dayDir = []
fileList.forEach(item => {
console.log("fs_id:", item.fs_id);
console.log("path:", item.path);
fsId.push(item.fs_id)
dayDir.push(item.path)
});
if (!bdstoken) throw new Error('bdstoken 获取失败');
// 3转存
/* ===== 构造查询字符串(10 个字段) ===== */
const qs = new URLSearchParams({
shareid: shareid,
from: uk,
sekey: decodeURIComponent(sekey),
bdstoken: bdstoken,
});
console.log('✅ 构造查询字符串成功', qs.toString());
/* ===== 构造 body(仅 2 个字段) ===== */
const body = new URLSearchParams({
fsidlist: JSON.stringify(fsId), // "[123,456]"
path: '/share' // "/share_2025-09-12"
});
/* ===== 真正发请求 ===== */
const transfer = await client.post(
`https://pan.baidu.com/share/transfer?${qs.toString()}`,
body,
{ headers: { Referer: SHARE_URL } }
);
console.log('✅ 转存进度:', transfer.data);
if (transfer.data.errno !== 0 && transfer.data.errno !== 4) throw new Error('转存失败 errno=' + transfer.data.errno); // 4是超时,但是大部分原因都是二次转存会有这个bug,百分之八十的概率是网盘已存在了,直接去分享
console.log('✅ 转存完成 → ');
await sleep(3000); // 转存后三秒再去刷新列表分享
/* 3.5 刷新自己的文件列表,取新 fs_id */
const mine = await client.get(
`https://pan.baidu.com/api/list?dir=/share&order=name&desc=0&num=200`,
{ headers: { Referer: 'https://pan.baidu.com/disk/home' } }
);
if (mine.data.errno !== 0) throw new Error('刷新自己列表失败');
console.log('✅ 刷新自己列表成功');
const myFsIds = mine.data.list.map(f => f.fs_id);
console.log('✅ 自己网盘新 fs_id 数组', myFsIds);
/* 4. 再分享 → 新链接 */
const qss = new URLSearchParams({
channel: 'chunlei',
bdstoken,
clienttype: 0,
web: 1,
});
// 随机四位
const newPwd = Math.random().toString(10).slice(2, 6);
const bodys = new URLSearchParams({
isKnowledge: 0,
public: 0,
period: 365,
pwd: newPwd, // 4 位提取码,可换
eflag: 'disable',
linkOrQrcode: 'link',
channel_list: '[]',
schannel: 4,
fid_list: JSON.stringify(myFsIds) // 必须是 JSON 字符串
});
const set = await client.post(
`https://pan.baidu.com/share/pset?${qss.toString()}`,
bodys,
{ headers: { Referer: 'https://pan.baidu.com/disk/home' } }
);
console.log('✅ 分享进度:', set.data);
if (set.data.errno !== 0) throw new Error('分享失败 errno=' + set.data.errno);
const { link, shortlink } = set.data;
console.log('🎉 新分享链接:', shortlink || link);
console.log('🎉 提取码:', newPwd);
}
} catch (e) {
console.error('❌', e.message);
}
})();运行
js
node index.js