夸克网盘目录树生成:
4层(高速并发版🚀,10分钟内)
若只需要导出3层修改 const MAX_DEPTH=4; 后面参数为3即可
测试:对13.5TB共81000个文件夹的网课视频目录扫描
3层仅需20秒左右
4层需5-10分钟
(async () => {
/* 自动读取分享 */
const raw=JSON.parse(sessionStorage.getItem("_share_args"))?.value;
if(!raw){alert("请在分享文件列表页运行");return;}
const pwd=raw.pwd_id;
const st=encodeURIComponent(raw.stoken);
console.log("扫描分享:",pwd);
/* 参数 */
const MAX_DEPTH=4;
const CONCURRENCY=8;
const RETRY=4;
let visited=new Set();
let queue=[{fid:"0",path:"",depth:0}];
let results=[];
function sleep(t){return new Promise(r=>setTimeout(r,t));}
async function fetchPage(fid,page){
for(let i=0;i<RETRY;i++){
try{
const r=await fetch(
`https://drive-pc.quark.cn/1/clouddrive/share/sharepage/detail?pr=ucpro&fr=pc&pwd_id=${pwd}&stoken=${st}&pdir_fid=${fid}&force=0&_page=${page}&_size=50`,
{credentials:"include"});
if(r.status===400) throw "参数失效";
return await r.json();
}catch(e){
await sleep(800+Math.random()*1200);
}
}
return null;
}
async function scanDir(task){
if(task.depth>MAX_DEPTH)return;
let page=1;
while(true){
const j=await fetchPage(task.fid,page);
if(!j?.data?.list?.length)break;
for(const f of j.data.list){
const full=task.path+"/"+f.file_name;
results.push(full);
if(f.dir&&!visited.has(f.fid)){
visited.add(f.fid);
queue.push({fid:f.fid,path:full,depth:task.depth+1});
}
}
page++;
await sleep(120+Math.random()*180);
}
}
async function worker(id){
while(queue.length){
const task=queue.shift();
if(!task)break;
await scanDir(task);
if(id===0)
console.log(`已扫:${results.length} | 目录:${visited.size} | 队列:${queue.length}`);
}
}
console.log("开始扫描…");
await Promise.all(Array.from({length:CONCURRENCY},(_,i)=>worker(i)));
console.log("完成:",results.length);
const txt=results.join("\n");
try{await navigator.clipboard.writeText(txt);}catch(e){}
const blob=new Blob([txt]);
const a=document.createElement("a");
a.href=URL.createObjectURL(blob);
a.download="quark目录.txt";
a.click();
})();
thonny单颗树
import html
input_file = r"C:\Users\JinRC\Downloads\quark目录 (5).txt"
output_file = r"C:\Users\JinRC\Downloads\quark目录 (5)tree.html"
# ---------- 构建树 ----------
tree = {}
with open(input_file, "r", encoding="utf-8") as f:
for line in f:
path = line.strip().strip("/")
if not path:
continue
parts = path.split("/")
node = tree
for p in parts:
node = node.setdefault(p, {})
# ---------- 生成HTML ----------
def render(node):
html_parts = ["<ul>"]
for name, child in sorted(node.items()):
safe = html.escape(name)
if child:
html_parts.append(
f'<li class="folder"><span class="toggle">📁 {safe}</span>'
)
html_parts.append(render(child))
html_parts.append("</li>")
else:
html_parts.append(f"<li class='file'>📄 {safe}</li>")
html_parts.append("</ul>")
return "\n".join(html_parts)
html_content = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>目录树</title>
<style>
body {{
font-family: Consolas, monospace;
background:#0f172a;
color:#e5e7eb;
}}
ul {{
list-style:none;
padding-left:18px;
}}
.folder > ul {{
display:none;
}}
.toggle {{
cursor:pointer;
color:#60a5fa;
}}
.file {{
color:#d1d5db;
}}
</style>
<script>
document.addEventListener("click",function(e){{
if(e.target.classList.contains("toggle")){{
let ul=e.target.parentNode.querySelector("ul");
if(ul) ul.style.display=ul.style.display=="none"?"block":"none";
}}
}});
</script>
</head>
<body>
<h2>资源目录</h2>
{render(tree)}
</body>
</html>
"""
with open(output_file, "w", encoding="utf-8") as f:
f.write(html_content)
print("完成 →", output_file)
thonny合并n颗树
合并几棵树就粘贴进去几棵树的文件路径
下面以3棵树举列
import html
from pathlib import Path
# ====== 需要合并的 txt 文件 ======
files = [
r"C:\Users\rckin\Downloads\quark目录 (1).txt",
r"C:\Users\rckin\Downloads\quark目录 (2).txt",
r"C:\Users\rckin\Downloads\quark目录 (3).txt"
]
# ====== 输出 html ======
output_file = r"C:\Users\JinRC\Downloads\directory_tree_merged.html"
# ===============================
# 构建树结构
# ===============================
tree = {}
def add_path(path):
parts = path.strip().strip("/").split("/")
node = tree
for p in parts:
if not p:
continue
node = node.setdefault(p, {})
for file in files:
with open(file, "r", encoding="utf-8") as f:
for line in f:
line=line.strip()
if line:
add_path(line)
# ===============================
# 渲染HTML树
# ===============================
def render(node):
html_parts=["<ul>"]
for name,child in node.items(): # ⚠ 不排序,避免10万文件卡死
safe=html.escape(name)
if child:
html_parts.append(f'<li class="folder"><span class="toggle">📁 {safe}</span>')
html_parts.append(render(child))
html_parts.append("</li>")
else:
html_parts.append(f"<li class='file'>📄 {safe}</li>")
html_parts.append("</ul>")
return "\n".join(html_parts)
# ===============================
# HTML模板(不能用f-string)
# ===============================
html_template = """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>资源目录</title>
<style>
body{
font-family:Consolas, monospace;
background:#0f172a;
color:#e5e7eb;
padding:20px;
}
h2{
color:#93c5fd;
}
ul{
list-style:none;
padding-left:18px;
}
.folder>ul{
display:none;
}
.toggle{
cursor:pointer;
color:#60a5fa;
}
.toggle:hover{
color:#93c5fd;
}
.file{
color:#d1d5db;
}
</style>
<script>
document.addEventListener("click",function(e){
if(e.target.classList.contains("toggle")){
let ul=e.target.parentNode.querySelector("ul");
if(ul){
ul.style.display = ul.style.display=="none"?"block":"none";
}
}
});
</script>
</head>
<body>
<h2>资源目录</h2>
__TREE__
</body>
</html>
"""
# 注入树
html_content = html_template.replace("__TREE__", render(tree))
# ===============================
# 写入文件
# ===============================
Path(output_file).write_text(html_content, encoding="utf-8")
print("完成!生成文件:")
print(output_file)
评论区