Skip to content
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