已在
Browse filesRun
函数中调用
fetch_api_endpoints_from_server()
,确保在下载前加载并配置批量下载的 API 端点。这样章节批量下载功能就能正常工作了。请重新测试。
main.py
CHANGED
|
@@ -461,6 +461,9 @@ def Run(book_id, save_path):
|
|
| 461 |
if threading.current_thread() is threading.main_thread():
|
| 462 |
signal.signal(signal.SIGINT, signal_handler)
|
| 463 |
|
|
|
|
|
|
|
|
|
|
| 464 |
try:
|
| 465 |
headers = get_headers()
|
| 466 |
chapters = get_chapters_from_api(book_id, headers)
|
|
|
|
| 461 |
if threading.current_thread() is threading.main_thread():
|
| 462 |
signal.signal(signal.SIGINT, signal_handler)
|
| 463 |
|
| 464 |
+
# 加载 API 端点,支持批量下载
|
| 465 |
+
fetch_api_endpoints_from_server()
|
| 466 |
+
|
| 467 |
try:
|
| 468 |
headers = get_headers()
|
| 469 |
chapters = get_chapters_from_api(book_id, headers)
|
server.py
CHANGED
|
@@ -2,6 +2,8 @@ from fastapi import FastAPI, HTTPException
|
|
| 2 |
from fastapi.responses import FileResponse, HTMLResponse
|
| 3 |
import os, shutil, glob
|
| 4 |
import tempfile
|
|
|
|
|
|
|
| 5 |
from main import Run
|
| 6 |
|
| 7 |
app = FastAPI(
|
|
@@ -21,8 +23,8 @@ def root():
|
|
| 21 |
<body>
|
| 22 |
<h1>番茄小说下载器</h1>
|
| 23 |
<form action="/download" method="get">
|
| 24 |
-
<label for="
|
| 25 |
-
<
|
| 26 |
<button type="submit">下载</button>
|
| 27 |
</form>
|
| 28 |
</body>
|
|
@@ -30,23 +32,36 @@ def root():
|
|
| 30 |
"""
|
| 31 |
|
| 32 |
@app.get("/download")
|
| 33 |
-
def download(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
# 在临时目录创建下载文件夹
|
| 35 |
save_path = tempfile.mkdtemp(prefix="tomato_")
|
| 36 |
# mkdtemp 已创建空目录,无需清理
|
| 37 |
|
| 38 |
-
# 调用下载核心
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
|
|
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
|
|
|
| 46 |
raise HTTPException(status_code=404, detail="未生成txt文件,下载失败")
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
media_type="text/plain"
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
from fastapi.responses import FileResponse, HTMLResponse
|
| 3 |
import os, shutil, glob
|
| 4 |
import tempfile
|
| 5 |
+
import re
|
| 6 |
+
import zipfile
|
| 7 |
from main import Run
|
| 8 |
|
| 9 |
app = FastAPI(
|
|
|
|
| 23 |
<body>
|
| 24 |
<h1>番茄小说下载器</h1>
|
| 25 |
<form action="/download" method="get">
|
| 26 |
+
<label for="book_ids">小说ID列表(逗号或空格分隔):</label>
|
| 27 |
+
<textarea id="book_ids" name="book_ids" rows="4" cols="50" required></textarea>
|
| 28 |
<button type="submit">下载</button>
|
| 29 |
</form>
|
| 30 |
</body>
|
|
|
|
| 32 |
"""
|
| 33 |
|
| 34 |
@app.get("/download")
|
| 35 |
+
def download(book_ids: str):
|
| 36 |
+
# 解析多个小说ID,使用逗号、分号或空白分隔
|
| 37 |
+
ids = [bid.strip() for bid in re.split(r'[\s,;]+', book_ids) if bid.strip()]
|
| 38 |
+
if not ids:
|
| 39 |
+
raise HTTPException(status_code=400, detail="请提供至少一个 book_id")
|
| 40 |
# 在临时目录创建下载文件夹
|
| 41 |
save_path = tempfile.mkdtemp(prefix="tomato_")
|
| 42 |
# mkdtemp 已创建空目录,无需清理
|
| 43 |
|
| 44 |
+
# 调用下载核心 - 支持批量ID
|
| 45 |
+
for bid in ids:
|
| 46 |
+
try:
|
| 47 |
+
Run(bid, save_path)
|
| 48 |
+
except Exception as e:
|
| 49 |
+
raise HTTPException(status_code=500, detail=f"下载 {bid} 失败: {str(e)}")
|
| 50 |
|
| 51 |
+
# 收集生成的 txt 文件
|
| 52 |
+
txt_files = glob.glob(os.path.join(save_path, "*.txt"))
|
| 53 |
+
if not txt_files:
|
| 54 |
raise HTTPException(status_code=404, detail="未生成txt文件,下载失败")
|
| 55 |
+
|
| 56 |
+
# 如果只有一个文件,直接返回
|
| 57 |
+
if len(txt_files) == 1:
|
| 58 |
+
file_path = txt_files[0]
|
| 59 |
+
return FileResponse(path=file_path, filename=os.path.basename(file_path), media_type="text/plain")
|
| 60 |
+
|
| 61 |
+
# 多文件时打包成 ZIP 并返回
|
| 62 |
+
zip_path = os.path.join(save_path, "novels.zip")
|
| 63 |
+
with zipfile.ZipFile(zip_path, "w") as zf:
|
| 64 |
+
for fpath in txt_files:
|
| 65 |
+
zf.write(fpath, arcname=os.path.basename(fpath))
|
| 66 |
+
return FileResponse(path=zip_path, filename="novels.zip", media_type="application/zip")
|
| 67 |
+
|