上一篇中,我们发现有些下载的内容无法正常识别,在 Emby 中直接显示为文件名。在前文中已经提到,这是因为字幕组没有遵循 Emby 的命名造成的。正确的文件夹结构应该是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
├── 前辈是男孩子
│   └── Season01
│   ├── S01E01.mkv
│   ├── S01E02.mkv
│   ├── S01E03.mkv
│   ├── S01E04.mkv
│   ├── S01E05.mkv
│   ├── S01E06.mkv
│   ├── S01E07.mkv
│   ├── S01E08.mkv
│   ├── S01E09.mkv
│   ├── S01E10.mkv
│   ├── S01E11.mkv
│   └── S01E12.mkv
...

因此,我们急需一个自动重命名/创建文件夹结构的解决方案。

于是,我找到了这个:AutoAnimeMv,一个可以自动查询+重命名+整理的脚本。

看看它的文档,真的非常简单。

我总结下,就这几步。

  1. 装好 Python
  2. pip 安装 requests 和 zhconv
  3. QB 配置运行外部程序

没了。

如果你的 Qbittorrent 在宿主机上运行,那么连奶奶都会用,有手就行。

……但我们现在是容器环境,事情就变得复杂起来了。

Docker 内外不互通

啥叫容器?生活中我们把盛放某种东西的、密封的盒子/罐子等叫做容器。密闭性是容器的必备要素。

Docker 也一样,容器里面不能直接访问外部的程序、资源等。

这就麻烦了,因为我们无法调用外部的 Python 脚本。

要解决这个问题,我探索了下面的三种解决方案:

  • 进入容器内部,装好 Python、Pip,然后把脚本放入容器,用 Qbittorrent 执行
  • 把外部 Python 主程序挂载到内部(挂载 /bin 到容器内)
  • 在原有 QB 基础上,自定义容器镜像,加入 Pip 和 AAM

先说结论,第一种不知为何 QB 无法正常调用 Python,日志里显示确实调用了,但是脚本实际上并没有执行。

第二种,无论如何指定绝对路径,docker 似乎都会直接使用容器内部的 Python,而不是外部的 Python。

只有第三种,自己搞镜像,才是真正能成功的方式。

如果你不想麻烦,想直接搞一个开箱即用的镜像,我已经帮你构建好了,你可以跳转到拉取我的镜像直接阅读。

但是,我还是很推荐你阅读剩下的内容,来更加深入地了解 Docker。(你可以跳过第一种和第二种方法)

Docker

进入容器内部执行命令

先来说说第一种方法。

怎么进入容器内呢?用下面的命令!

1
docker exec -it qbittorrent /bin/bash

这条命令是什么意思呢?

exec,就是 execute 的缩写,即在容器内部执行命令。-it,i 表示 interacitve,用它可以打开标准输入,让容器内部收到我们输入的内容。t 表示 tty,即伪终端,让我们能够创建新的终端,而不是只有输入输出。如果不加上 t,你会发现root@798bebd6b61c:/# 这一串没了,就是因为只打开了输入输出,你可以执行 bash 命令,但是无法以终端的方式执行,而是像命令行程序一样,只有输入+输出。如果只用 t,那么你会得到一个无法输入命令的终端,因为缺少输入。

/bin/bash 就是想要使用的容器内 shell 啦。

接下来就是在内部配置 Python 和 Pip 了,这些不多讲了,因为这种方式实在是太过投机取巧,而且事实证明根本无法正常使用。

挂载外部 bin

这部分也不多讲,就是和之前一样,在 docker-compose.yml 里面加一下路径映射,把 /usr/bin 映射到内部。前面也说了,由于里面已经有 Python 了,所以似乎无法使用外部的 Python(即使你指定了绝对路径)

构建自己的镜像

好了,这才是重头戏!

我们之前都是用 docker-compose 来拉取别人写好的镜像,现在是时候构建我们自己的了!

不过,在开始之前,我希望你了解以下 docker 命令:

1
2
3
docker stop <name/id>
docker restart <name/id>
docker remove <name/id>

分别是停止、重启、移除容器。和字面意思相同,就是管理容器启停的命令。

现在新建一个叫 Dockerfile 的文件(没有后缀名!)

1
2
3
4
5
6
FROM tlan16/qbittorrent-enhanced
RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py \
&& python get-pip.py --break-system-packages
RUN python -m pip install requests --break-system-packages \
&& python -m pip install zhconv --break-system-packages
ADD AutoAnimeMv.py /amv/AutoAnimeMv.py

WHAT?突然写啥鬼画符呢?

别急,我们一步步来解释。

FROM,从、自,这是指定了基础镜像(把一个镜像当作起点)。

RUN,就是在基础镜像中运行命令(从起点出发,开始自定义)。

ADD,就是在镜像中加入文件。

上面的代码的含义,就是做了下面的事情

  1. 下载 tlan16/qbittorrent-enhanced 作为基础镜像
  2. 下载并执行 get-pip.py,安装 pip
  3. 安装 requests zhconv 库
  4. 把 AAM.py 加入容器内部 /amv/AutoAnimeMv.py

现在保存文件,然后下载 AAM.py。放到你 Dockerfile 相同的文件夹。

注意,上面链接里面的 AAM 是我的魔改版(只改了一个配置,默认打开硬链接防止做种失效),请参阅 https://github.com/SamHou0/qbittorrent-enhanced-aam-docker 了解更多信息。

现在,命令行输入

1
docker build -t qbittorrent-enhanced-aam .

-t 指定了镜像标签,后面的 . 就是用当前目录开始构建。

OK,等他 build 完成,然后就可以编辑你的 docker-compose.yml,改成

1
image: qbittorrent-enhanced-aam

然后启动即可!

拉取我的镜像

我已经把构建好包含 AAM 的镜像上传到了 Docker Hub,只要把你的 image 改成

1
image: samhou0/qbittorrent-enhanced-aam

然后重新 docker-compose 部署即可!

配置 AAM

这部分就简单了。

根据开发者的说法,你需要完成下面的步骤:

  • Torrent 内容布局改为不创建子文件夹
  • 添加一个 Bangumi 分类
  • 在下载 - torrent 完成时运行外部程序中,填入 python /usr/share/AutoAnimeMv.py --filepath "%D" --filename "%N" --number "%C" --categoryname "%L"
  • 下载番剧时,选中 Bangumi 分类(不需要更改你的下载文件夹!)

然后,下载完毕后,你的文件夹会是这样的:

1
2
3
4
5
6
7
└── downloads
├── 2025-02-06.log
├── Bangumi
│   └── 我与尼特女忍者的莫名同居生活
│   └── Season01
│   └── S01E05.mkv
├── [LoliHouse] NEET Kunoichi to Nazeka Dousei Hajimemashita - 05 [WebRip 1080p HEVC-10bit AAC SRTx2].mkv

做种完全不影响,然后你只要把 Bangumi 文件夹挂载到你的 Emby 上就行了(第三篇写过了,不再赘述)

写在后面

好了,这个系列到这里也就告一段落了~

怎么样,有学到什么知识吗?

在写作的过程中,我也学到了很多新东西呢,比如 docker 的挂载、权限,以及 Dockerfile 的编写,也学会了很多 Linux 命令。希望这个系列能够为大家带来一些收获~我们下个系列再见!