Skip to content

y08lin4/qbapi-pt-

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

好的,这是一份可以直接复制粘贴到 GitHub README.md 文件中的完整手册。

它整合了您编写的部署指南、我们最终完善的脚本代码,并采用标准的 GitHub Markdown 格式,包含了标题、特性列表、代码折叠等元素,使其看起来非常专业和清晰。

qBittorrent Ratio Management Daemon

一个工程师级的 qBittorrent 守护进程,用于根据分享率自动管理种子的状态。

它会在后台安静地运行,自动监控指定分类的种子。当分享率达到设定阈值后,它会自动暂停该种子;暂停一段时间后,再自动恢复。

本项目遵循 Linux 最佳实践,通过 systemd 部署为一个安全、稳定且能自我恢复的后台服务。一旦配置好,它会默默地为你值班,像个不喝咖啡的老运维。

✨ 特性

自动监控:定期检查指定分类下所有种子的分享率。

智能暂停/恢复:达到分享率阈值后自动暂停,暂停期满后自动恢复。

状态持久化:将自己暂停的种子列表保存在本地,即使脚本或服务器重启,状态也不会丢失。

登录续期:自动处理 qBittorrent Web UI 的登录会话过期问题。

异常自恢复:当无法连接到 qBittorrent 时,会自动进入冷却期并尝试重连,而不是崩溃退出。

守护进程化:通过 systemd 管理,实现开机自启、进程守护和统一的日志记录。

轻量可靠:资源占用极低,逻辑清晰,稳如老狗,不乱报错。

📜 脚本代码

点击展开/折叠 qb_ratio_manager.py 脚本代码

code Python download content_copy expand_less import requests import time import json from datetime import datetime, timedelta import os

--- 用户配置 ---

qBittorrent Web UI 地址和端口

QB_HOST = "localhost" QB_PORT = 8080

你的 qBittorrent 用户名和密码

QB_USERNAME = "admin" QB_PASSWORD = "your_password"

要监控的分类名称

TARGET_CATEGORY = "my-category"

达到此分享率后触发暂停 (例如 2.0)

TARGET_RATIO = 2.0

暂停多少分钟

PAUSE_MINUTES = 60

每次检查的间隔时间(秒)

CHECK_INTERVAL_SECONDS = 60

连接 qBittorrent 失败后的冷却时间(秒)

CONNECTION_FAILURE_COOLDOWN = 300

网络请求超时时间(秒)

REQUEST_TIMEOUT = 10

状态持久化文件

STATE_FILE = "qb_ratio_manager_state.json"

--- 配置结束 ---

构建基础 URL

BASE_URL = f"http://{QB_HOST}:{QB_PORT}"

全局变量

session = requests.Session()

格式: { "torrent_hash": "YYYY-MM-DDTHH:MM:SS.ffffff" }

paused_by_script = {}

def log(message): """带时间戳的日志输出""" print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {message}")

def login(): """登录到 qBittorrent API 并保持会话""" log("正在尝试登录...") try: url = f"{BASE_URL}/api/v2/auth/login" data = {"username": QB_USERNAME, "password": QB_PASSWORD} response = session.post(url, data=data, timeout=REQUEST_TIMEOUT) response.raise_for_status() if "Ok." in response.text: log("成功登录到 qBittorrent API。") return True else: log(f"登录失败,响应: {response.text}") return False except requests.exceptions.RequestException as e: log(f"登录时连接 qBittorrent 失败: {e}") return False

def ensure_login(): """检查登录状态,如果过期则重新登录""" try: url = f"{BASE_URL}/api/v2/app/version" response = session.get(url, timeout=REQUEST_TIMEOUT) if response.status_code == 403: # Forbidden log("登录会话已过期,正在重新登录...") return login() response.raise_for_status() return True except requests.exceptions.RequestException: raise

def load_state(): """从文件加载脚本暂停的种子状态""" global paused_by_script if not os.path.exists(STATE_FILE): log("未找到状态文件,将创建新的状态。") return try: with open(STATE_FILE, "r") as f: if os.path.getsize(STATE_FILE) == 0: log("状态文件为空,将使用空的状态开始。") return iso_data = json.load(f) paused_by_script = {h: datetime.fromisoformat(t) for h, t in iso_data.items()} log(f"成功从 {STATE_FILE} 加载了 {len(paused_by_script)} 条状态记录。") except (json.JSONDecodeError, IOError) as e: log(f"加载状态文件失败: {e}。将使用空的状态开始。") paused_by_script = {}

def save_state(): """将脚本暂停的种子状态保存到文件""" try: with open(STATE_FILE, "w") as f: iso_data = {h: t.isoformat() for h, t in paused_by_script.items()} json.dump(iso_data, f, indent=4) except IOError as e: log(f"保存状态文件失败: {e}")

def get_torrents(): """获取指定分类下的所有种子信息""" try: url = f"{BASE_URL}/api/v2/torrents/info" params = {"category": TARGET_CATEGORY, "filter": "all"} response = session.get(url, params=params, timeout=REQUEST_TIMEOUT) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: log(f"获取种子列表失败: {e}") except json.JSONDecodeError: log("解析种子列表失败,收到的不是有效的 JSON。") return None

def pause_torrents(hashes): """暂停指定的种子""" if not hashes: return try: url = f"{BASE_URL}/api/v2/torrents/pause" session.post(url, data={"hashes": "|".join(hashes)}, timeout=REQUEST_TIMEOUT).raise_for_status() log(f"已暂停 {len(hashes)} 个种子: {', '.join(hashes)}") except requests.exceptions.RequestException as e: log(f"暂停种子失败: {e}")

def resume_torrents(hashes): """恢复指定的种子""" if not hashes: return try: url = f"{BASE_URL}/api/v2/torrents/resume" session.post(url, data={"hashes": "|".join(hashes)}, timeout=REQUEST_TIMEOUT).raise_for_status() log(f"已恢复 {len(hashes)} 个种子: {', '.join(hashes)}") except requests.exceptions.RequestException as e: log(f"恢复种子失败: {e}")

def main_loop(): """主循环,执行监控和管理任务""" if not ensure_login(): log("无法维持登录状态,跳过此次检查。") return now = datetime.now() state_changed = False torrents_to_resume = [h for h, t in paused_by_script.items() if now >= t + timedelta(minutes=PAUSE_MINUTES)] if torrents_to_resume: resume_torrents(torrents_to_resume) for h in torrents_to_resume: paused_by_script.pop(h, None) state_changed = True torrents = get_torrents() if torrents is None: return torrents_to_pause = [t['hash'] for t in torrents if t['ratio'] >= TARGET_RATIO and 'paused' not in t['state'].lower() and t['hash'] not in paused_by_script] if torrents_to_pause: pause_torrents(torrents_to_pause) for h in torrents_to_pause: paused_by_script[h] = now state_changed = True if state_changed: save_state() log(f"检查完成。脚本正在管理 {len(paused_by_script)} 个种子。")

if name == "main": load_state() if not login(): log("初始登录失败,请检查配置。脚本将在冷却后重试。") time.sleep(CONNECTION_FAILURE_COOLDOWN) log("开始监控任务... 服务已启动。") while True: try: main_loop() time.sleep(CHECK_INTERVAL_SECONDS) except requests.exceptions.ConnectionError as e: log(f"无法连接到 qBittorrent: {e}。将在 {CONNECTION_FAILURE_COOLDOWN // 60} 分钟后重试。") time.sleep(CONNECTION_FAILURE_COOLDOWN) except KeyboardInterrupt: break log("服务正在停止... 正在保存最终状态...") save_state() log("状态已保存。服务已退出。")

🚀 在 Debian 12 上的部署指南

本指南将引导你将脚本部署为一个稳定、可自恢复的 systemd 后台服务。

🧩 前提条件

你已拥有一台 Debian 12 服务器并可通过 SSH 登录。

你拥有 sudo 权限。

你的 qBittorrent Web UI 已启用。

第 0 步:准备环境和依赖

更新软件包列表

code Bash download content_copy expand_less sudo apt update

安装 Python 3 与 pip

code Bash download content_copy expand_less sudo apt install python3 python3-pip -y

安装 requests 库

code Bash download content_copy expand_less pip3 install requests

(推荐)创建专用用户 创建一个最小权限用户来运行脚本,以增强安全性。

code Bash download content_copy expand_less sudo adduser --system --group --no-create-home qb-manager 第 1 步:部署脚本

创建应用目录

code Bash download content_copy expand_less sudo mkdir /opt/qb-manager

创建脚本文件

code Bash download content_copy expand_less sudo nano /opt/qb-manager/qb_ratio_manager.py

将上面的 Python 脚本代码完整粘贴进去。切记修改文件顶部的用户配置部分,填入你的 qBittorrent 信息。

设置所有权

code Bash download content_copy expand_less sudo chown -R qb-manager:qb-manager /opt/qb-manager 第 2 步:创建 systemd 服务文件

这是部署的核心,它告诉系统如何管理我们的脚本。

创建服务文件

code Bash download content_copy expand_less sudo nano /etc/systemd/system/qb-manager.service

粘贴服务配置

code Ini download content_copy expand_less [Unit] Description=qBittorrent Ratio Management Daemon After=network.target

[Service] User=qb-manager Group=qb-manager WorkingDirectory=/opt/qb-manager ExecStart=/usr/bin/python3 /opt/qb-manager/qb_ratio_manager.py Restart=on-failure RestartSec=30 StandardOutput=journal StandardError=journal

[Install] WantedBy=multi-user.target 第 3 步:启动与管理服务

重载 systemd 配置

code Bash download content_copy expand_less sudo systemctl daemon-reload

启动服务

code Bash download content_copy expand_less sudo systemctl start qb-manager.service

检查服务状态

code Bash download content_copy expand_less sudo systemctl status qb-manager.service

如果一切正常,Active: 状态应显示为 active (running)。

设置开机自启

code Bash download content_copy expand_less sudo systemctl enable qb-manager.service 第 4 步:查看日志与维护

服务的所有输出都由 journald 统一管理。

查看完整日志:

code Bash download content_copy expand_less sudo journalctl -u qb-manager.service

实时跟踪日志:

code Bash download content_copy expand_less sudo journalctl -u qb-manager.service -f 常用管理命令 动作 命令 停止服务 sudo systemctl stop qb-manager.service 重启服务 sudo systemctl restart qb-manager.service 禁止自启 sudo systemctl disable qb-manager.service 💡 可选优化:使用 Python 虚拟环境

为了避免系统级的 Python 依赖冲突,强烈建议使用虚拟环境(venv)。

创建虚拟环境

code Bash download content_copy expand_less sudo apt install python3-venv -y sudo -u qb-manager python3 -m venv /opt/qb-manager/venv

在虚拟环境中安装依赖

code Bash download content_copy expand_less sudo /opt/qb-manager/venv/bin/pip install requests

修改 systemd 服务文件 将 ExecStart 指令修改为使用虚拟环境中的 Python 解释器:

code Ini download content_copy expand_less ExecStart=/opt/qb-manager/venv/bin/python /opt/qb-manager/qb_ratio_manager.py

修改后,记得执行 sudo systemctl daemon-reload 和 sudo systemctl restart qb-manager.service。

📄 授权

本项目采用 MIT License。您可以自由使用、修改和分发。

About

动态控制种子的分享率

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages