nodejs实现夸克网盘转存
新建文件夹并初始化
js
npm init -y安装依赖包
js
npm install axios创建config.js文件
js
module.exports = {
// 必填:把你浏览器里完整的 Cookie 字符串粘过来
cookie: '',
// 可选:接口限流,单位 ms(默认20000,也就是批量上传,每两个间隔20秒上传一个文件,防止限流,不做批量上传的话可以默认0)
sleep: 20000,
// 目前存储文件夹id(网盘里面详情信息里面有,自行去找,会将文件存储在这个id的文件夹下)
folderId: '',
};links.txt(存放链接的文件)
js
https://pan.quark.cn/s/70d9657c8678
https://pan.quark.cn/s/fba1d65775c4
https://pan.quark.cn/s/c9dfc984b065
https://pan.quark.cn/s/3b74b82acb35
https://pan.quark.cn/s/fa6f880dc34c
https://pan.quark.cn/s/1d2efc94d5d1
https://pan.quark.cn/s/0b767466979f
https://pan.quark.cn/s/a36a201e1791
https://pan.quark.cn/s/d794590ab6a2
https://pan.quark.cn/s/bc8e8c875074
https://pan.quark.cn/s/e25266fc45fc
https://pan.quark.cn/s/3a5280f8fb0a
https://pan.quark.cn/s/e17d05118faf
https://pan.quark.cn/s/fb26e1744219
https://pan.quark.cn/s/231ed85ba147
https://pan.quark.cn/s/d79e071b9e5e
https://pan.quark.cn/s/d46f18e025bd
https://pan.quark.cn/s/2fca2e371822
https://pan.quark.cn/s/59267f475240
https://pan.quark.cn/s/63f0816ab04c
https://pan.quark.cn/s/a069f3539fbd
https://pan.quark.cn/s/00955b40360a
https://pan.quark.cn/s/2710277e928d
https://pan.quark.cn/s/b560a2e26715
https://pan.quark.cn/s/186908545292
https://pan.quark.cn/s/06ab67f3a76e
https://pan.quark.cn/s/fb3c3fd7fe52index.js
js
/**
* 夸克网盘分享链接批量转存 —— 2025-06-18 官方路径实测
* 依赖:npm i axios
*/
const fs = require('fs');
const path = require('path');
const axios = require('axios');
const { cookie, sleep, folderId } = require('./config');
let flag = true;
let timer = null;
// 节流函数
const sleep2 = (ms) => {
// 返回promise
return new Promise((resolve, reject) => {
// 节流
if (flag) {
flag = false;
timer = setTimeout(() => {
flag = true;
clearTimeout(timer);
timer = null;
resolve();
}, ms);
}
});
}
const client = axios.create({
baseURL: 'https://drive-h.quark.cn',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
Cookie: cookie,
'Accept': 'application/json'
},
});
/* ===== 请求拦截器:打印真正发出去的完整信息 ===== */
client.interceptors.request.use(config => {
return config;
});
/* ===== 响应拦截器:打印返回状态 & 简要数据 ===== */
client.interceptors.response.use(
res => {
// console.log('[<<< RESPONSE <<<]');
// console.log('Status :', res.status);
// console.log('Data :', res.data);
return res;
},
err => {
console.log('[<<< ERROR <<<]');
if (err.response) {
console.log('Status :', err.response.status, err.response.statusText);
console.log('URL :', err.config?.baseURL + err.config?.url);
console.log('Params :', JSON.stringify(err.config?.params || {}, null, 2));
console.log('Body :', JSON.stringify(err.config?.data || {}, null, 2));
console.log('Resp :', JSON.stringify(err.response.data, null, 2));
} else {
console.log('Message:', err.message);
}
return Promise.reject(err);
}
);
(async () => {
const links = fs.readFileSync(path.join(__dirname, 'links.txt'), 'utf8')
.split(/\r?\n/)
.map(l => l.trim())
.filter(Boolean);
for (const shareUrl of links) {
try {
const { shareId, pwd } = parseShareUrl(shareUrl);
console.log(`\n开始转存:${shareId}`);
console.log('① 获取 token...');
const { stoken } = await getToken(shareId, pwd);
console.log('② 获取文件列表...');
const files = await getFileList(shareId, stoken);
if (!files.length) { console.log('分享为空'); continue; }
console.log('④ 转存中...');
let res = await saveFiles(shareId, stoken, folderId);
if (res) {
console.log(`✅ 转存完成:${shareId}`);
} else {
console.log(`❌ 转存失败:${shareId}`);
}
// 5. 生成新分享(仅成功)
console.log('⑤ 生成分享链接...');
const newShare = await createShare(res); // 目录id
console.log('✅ 分享链接:', newShare.url);
await sleep2(sleep);
} catch (e) {
await sleep2(sleep);
console.error(`❌ 失败:${shareUrl}`, e.message);
}
}
})();
/**
* 生成分享链接
* @param {string[]} fids 要分享的文件id
*/
async function createShare(fids) {
// 创建分享
const res = await client.post(
'/1/clouddrive/share?pr=ucpro&fr=pc',
{
fid_list: fids,
expired_type: 1, // 永久
title: '批量分享',
url_type: 1, // 2=私密(会返回 passcode)
}
);
console.log('创建分享成功:', res.data);
// 2. 轮询任务直到完成
for (let i = 0; i < 60; i++) { // 最多 60 秒
const { data } = await client.get(
'/1/clouddrive/task?pr=ucpro&fr=pc',
{ params: { task_id: res.data.data.task_id } }
);
const d = data.data;
if (data.status === 200 && d?.share_id) {
// 调用分享
const res3 = await client.post(
'/1/clouddrive/share/password?pr=ucpro&fr=pc',
{
share_id: d.share_id
}
);
if (res3.data.status == 200) {
console.log(`✅ 分享成功:${res3.data.data.share_url}`);
return {
url: res3.data.data.share_url
}
} else {
console.error(`❌ 创建分享失败:${res3.data.message}`);
return null;
}
}
await new Promise(r => setTimeout(r, 1000));
}
throw new Error('轮询超时,未拿到新文件 id');
}
/* ---------- 工具函数 ---------- */
function parseShareUrl(url) {
const u = new URL(url);
const shareId = u.pathname.split('/s/')[1].split(/[/#?]/)[0];
const pwd = u.searchParams.get('pwd') || '';
return { shareId, pwd };
}
async function getToken(shareId, pwd) {
const url = '/1/clouddrive/share/sharepage/token?pr=ucpro&fr=pc&uc_param_str=&__dt=176&__t=1757468424118';
console.log('[TOKEN REQ]', url, { share_id: shareId, passcode: pwd });
const { data } = await client.post(url, {
pwd_id: shareId,
support_visit_limit_private_share: true,
passcode: pwd || '' // 确保没密码时传空串
});
return { stoken: data.data.stoken };
}
async function getFileList(shareId, stoken) {
const { data } = await client.get(
'/1/clouddrive/share/sharepage/detail?pr=ucpro&fr=pc',
{ params: { pwd_id: shareId, stoken, _size: 50 } }
);
return data.data.list || [];
}
async function saveFiles(shareId, stoken, toPid) {
// 1. 发起保存(保存全部)
const { data: save } = await client.post(
'/1/clouddrive/share/sharepage/save?pr=ucpro&fr=pc',
{
exclude_fids: [],
fid_token_list: [],
pdir_fid: '0',
pwd_id: shareId,
stoken,
fid_list: [], // 空 = 保存全部
to_pdir_fid: toPid,
scene: 'link',
pdir_save_all: true
}
);
const taskId = save.data.task_id;
console.log('✅ 保存任务已提交,task_id:', taskId);
// 2. 轮询直到完成
for (let i = 0; i < 120; i++) { // 最多 120 秒
const { data } = await client.get(
'/1/clouddrive/task?pr=ucpro&fr=pc',
{ params: { task_id: taskId } }
);
const d = data?.data;
const status = data?.status;
console.log(`[轮询 ${i + 1}] status=${status}, save_as_top_fids=`, d?.save_as?.save_as_top_fids);
if (status === 200 && d?.save_as?.save_as_top_fids?.length > 0) {
console.log('✅ 转存完成,文件ID列表:', d.save_as.save_as_top_fids);
return d.save_as.save_as_top_fids;
}
await new Promise(r => setTimeout(r, 1000));
}
throw new Error('❌ 转存任务超时(120秒),仍未完成');
}运行
js
node index.js代码运行后就开始将上述网盘文件存储到指定的文件夹id下面,并分享出这个文件夹新的分享链接
