Benjy's Blog

「All In One 主机」— 电子书下载提取自动化

2025-07-05

自从买了掌阅之后基本就电子书自由了,又开始捣鼓电子书的管理。平常我都在 读书派 下载图书,这个网站每周基本都会更新2-4次最新的书籍,所以我基本上闲了就会上去看看新书里有没有喜欢的,然后直接保存。网站提供两种方式下载,诚通网盘和迅雷网盘,从便捷角度上来说还是迅雷方便一些。保存完毕后用迅雷云盘下载到本地,当然会有下载限速,但我也不着急,所以慢慢下。等下载下来之后处理图书和导入掌阅,其中处理图书这一步多少有点繁琐,下载的图书是zip格式的,内部一般会有三种格式,有时候还会提供pdf的版本,同时网站内部为了防止重名,还会用ID+书名重新命名,有的版本还会把书名改成拼音,所以我用的时候必须要改一次名字,多少有些麻烦,搞了两回就腻了。接着就懂了自动化的念头,想了想,整体方案部署在群辉上可行,说干就干。

整体流程

1
2
3
4
5
6
7
8
9
10
11
读书派看到喜欢的书

保存到迅雷云盘(ZIP 格式,文件名:ID-书名.zip)

群辉 Alist 挂载迅雷云盘(WebDAV)

群辉 Cloud Sync 自动同步新增文件 → /volume1/downloads/books-inbox/

群辉任务计划定期执行脚本(每天 18:00)我基本上晚上导入,也不会特别频繁

解压 ZIP → 提取电子书(epub/azw3/mobi/pdf)→ 改名 → 移动到 /volume1/books/

第一步:读书派保存到迅雷云盘

zip 文件参考

1
2
3
4
5
6
7
12345-置身事内.zip     
├── 12345-Zhi Shen Shi Nei.epub
├── 12345-Zhi Shen Shi Nei.pdf
├── 12345-Zhi Shen Shi Nei.azw3
├── 12345-Zhi Shen Shi Nei.mobi
├── 官方网址:www.dushupai.com.url
└── 版权声明.txt

几点说明:

  • 读书派提供的 zip 中,根据时间不同内容也不同,有时候有一种格式有时候有多种格式,命名有时候是中文有时候是拼音,外层文件夹是固定的ID+书名的组合
  • 脚本用 zip 外层文件名提取书名(去掉 ID 前缀),作为提取文件的名称
  • 按 epub → azw3 → mobi → pdf 优先级取第一个匹配的格式,其余忽略

第二步:群辉安装并配置 Alist

安装 Alist(Docker Compose方式)

这里使用 Docker Compose 的方式集成 Alist,虽然现在 Nas 都提供可视化操作,但是 Docker Compose 可以很方便的迁移备份。
将 Alist 的 Docker Compose 文件放到 /volume1/docker/alist 文件夹下:

1
2
3
4
5
6
7
8
9
10
11
version: '3.8'

services:
alist:
image: xhofe/alist:latest
container_name: alist
restart: unless-stopped
ports:
- "5244:5244"
volumes:
- /volume1/docker/alist/data:/opt/alist/data

SSH 进入该目录,执行启动:

1
docker-compose up -d

首次启动后查看初始密码:

1
docker logs alist | grep password

在 Alist 中添加迅雷云盘

  1. 浏览器打开 http://群辉IP:5244,用管理员账号登录
  2. 进入 存储添加
  3. 驱动选择 迅雷云盘
  4. 填写迅雷账号(手机号 + 密码,或扫码授权)
  5. 挂载路径建议填 /xunlei
  6. 保存后在 Alist 文件列表中确认能看到迅雷云盘文件

启用 WebDAV

Alist 默认开启 WebDAV,地址为:

1
http://群辉IP:5244/dav

第三步:配置 Cloud Sync 同步迅雷云盘

群辉 Cloud Sync 套件原生支持 WebDAV,图形界面配置,后台常驻自动同步新增文件,无需手写同步脚本。

安装 Cloud Sync

在群辉 套件中心 搜索 Cloud Sync 安装。

新建同步任务

  1. 打开 Cloud Sync → 新增
  2. 云服务商选择 WebDAV
  3. 填写连接信息:
项目
服务器地址 http://127.0.0.1:5244/dav/xunlei
用户名 Alist 管理员账号
密码 Alist 管理员密码
  1. 点击 下一步,配置同步选项:
项目
本地路径 /volume1/downloads/books-inbox
同步方向 仅下载(云端 → 本地)
同步规则 勾选”跳过已存在的文件”
  1. 保存后任务立即启动,后续云盘有新增 zip 会自动下载到 books-inbox

Cloud Sync 不支持通配符过滤扩展名,但迅雷云盘里存放的都是读书派 zip,无需额外过滤。如果云盘根目录混有其他文件,可在 Alist 中单独建一个子目录(如 /xunlei/books)专门存放读书派文件,Cloud Sync 只同步该子目录。


第四步:解压改名脚本

Cloud Sync 负责同步,脚本只需处理 books-inbox 里的 zip。

新建 /volume1/scripts/book-auto.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/bin/bash

# 并发保护:同一时间只允许一个实例运行
LOCK_FILE="/tmp/book-auto.lock"
exec 9>"$LOCK_FILE"
flock -n 9 || { echo "已有实例在运行,退出"; exit 0; }

SOURCE_DIR="${1:-/volume1/downloads/books-inbox}"
TARGET_DIR="${2:-/volume1/books}"
LOG="/volume1/scripts/logs/book-auto.log"
MAX_LOG_SIZE=$((5 * 1024 * 1024))

mkdir -p "$TARGET_DIR" "$(dirname "$LOG")"

[ -f "$LOG" ] && [ "$(stat -c%s "$LOG" 2>/dev/null || stat -f%z "$LOG")" -gt "$MAX_LOG_SIZE" ] && > "$LOG"

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG"; }

if [ ! -d "$SOURCE_DIR" ]; then
log "❌ 源目录不存在: $SOURCE_DIR"
exit 1
fi

cd "$SOURCE_DIR" || exit 1

zip_files=(*.zip)
[ ! -e "${zip_files[0]}" ] && { log "没有找到 zip 文件,退出"; exit 0; }

formats=("epub" "azw3" "mobi" "pdf")
success=0
failed=0
skipped=0

log "📦 共 ${#zip_files[@]} 个 zip 文件"

for zip_file in "${zip_files[@]}"; do
[ -e "$zip_file" ] || continue

zip_name="${zip_file%.zip}"
new_name=$(echo "$zip_name" | cut -d'-' -f2-)

if [ -z "$new_name" ] || [ "$new_name" = "$zip_name" ]; then
log "⚠️ $zip_name — 文件名不含横杠,跳过"
skipped=$((skipped + 1))
continue
fi

# 预先检测目标格式,判断是否已处理过
already_done=false
for fmt in "${formats[@]}"; do
if [ -f "${TARGET_DIR}/${new_name}.${fmt}" ]; then
log "⏭ ${new_name}.${fmt} 已存在,跳过"
already_done=true
skipped=$((skipped + 1))
break
fi
done
$already_done && continue

temp_dir="./${zip_name}_temp"
mkdir -p "$temp_dir"

# 完整性校验:拦截 Cloud Sync 尚未传完的残留 zip
if ! unzip -t "$zip_file" > /dev/null 2>&1; then
log "⚠️ $zip_name — zip 校验未通过,跳过(可能仍在下载中)"
rm -rf "$temp_dir"
continue
fi

if ! unzip -o -q "$zip_file" -d "$temp_dir" 2>/dev/null; then
log "❌ $zip_name — 解压失败"
rm -rf "$temp_dir"
failed=$((failed + 1))
continue
fi

book_file=""
book_type=""
for fmt in "${formats[@]}"; do
found=$(find "$temp_dir" -type f -iname "*.${fmt}" | head -1)
if [ -n "$found" ]; then
book_file="$found"
book_type="$fmt"
break
fi
done

if [ -z "$book_file" ]; then
log "❌ $zip_name — 未找到电子书文件"
rm -rf "$temp_dir"
failed=$((failed + 1))
continue
fi

dest="${TARGET_DIR}/${new_name}.${book_type}"
if mv -f "$book_file" "$dest" 2>/dev/null; then
log "✅ ${new_name}.${book_type}"
success=$((success + 1))
else
log "❌ $zip_name — 移动失败"
failed=$((failed + 1))
fi

rm -rf "$temp_dir"
done

log "📊 完成:✅ $success 个 ⏭ $skipped 个 ❌ $failed 个"
1
chmod +x /volume1/scripts/book-auto.sh

第五步:群辉任务计划配置

文件同步到本地之后,后面的操作就有很多方式了,可以在群辉中监听文件夹变动,也可以定时任务,对我这个场景来说,并不是一定要特别频繁监听,定时完全就能够满足了。

配置定时任务

  1. 打开群辉 控制面板任务计划新增计划的任务用户定义的脚本
  2. 只需创建一个任务:

任务:处理 inbox 中的 zip

项目
任务名称 book-auto
用户 root
计划 每天 18:00
脚本 /volume1/scripts/book-auto.sh

Cloud Sync 后台持续同步,定时任务只负责解压处理。unzip -t 校验会跳过尚未下载完的 zip,等下次运行时重试。flock 锁保证手动触发与定时任务不会并发冲突。


目录结构总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/volume1/
├── books/ # 最终电子书库
│ ├── 置身事内.epub
│ ├── 大国大城.epub
│ └── ...
├── downloads/
│ └── books-inbox/ # Cloud Sync 同步落地目录
│ └── (zip 文件)
├── scripts/
│ ├── book-auto.sh # 解压改名移动脚本
│ └── logs/
│ └── book-auto.log
└── docker/
└── alist/data/ # Alist 数据目录

判断逻辑

1
2
3
4
5
books-inbox/12345-置身事内.zip

books/置身事内.epub 存在?
├── 是 → 跳过(已处理)
└── 否 → 解压、改名、移动到 books/

book-auto.sh 在解压前先检查 TARGET_DIR/${书名}.{epub,azw3,mobi,pdf} 是否存在;存在任意一种格式即视为已处理,直接跳过该 zip。

本地 inbox 目录的状态含义

inbox 中有 zip books 中有对应书 含义
已下载,待提取(下次 18:00 会处理)
已下载且已提取(zip 作为本地原始备份)
zip 被手动删除,books 中的书不受影响
云盘有但本地尚未同步,等下次同步

手动触发(调试用)

1
2
# 手动处理 inbox 中的 zip
/volume1/scripts/book-auto.sh

常见问题

1、Q:Cloud Sync 提示连接失败

检查 Alist 是否正常运行:docker ps | grep alist;确认 WebDAV 地址和账号密码正确。

2、Q:Alist 重启后迅雷云盘 token 失效

重新进入 Alist 管理界面,编辑迅雷云盘存储,重新授权即可。


Tags: PVE