
1. 项目概述作为一个B站深度用户我发现自己经常错过关注的UP主发布的新视频。手动刷新空间页、等待动态更新效率低下且容易遗漏。为了解决这个痛点我动手写了一个自动化追踪工具——Bilibili UP Update Tracker。这个工具的核心功能很简单自动监控你指定的UP主列表一旦他们发布了新视频就立刻通过邮件通知你让你再也不会错过任何一次更新。这个项目本质上是一个轻量级的Python脚本它巧妙地利用了B站的公开API结合异步请求和邮件服务构建了一个稳定、高效的监控系统。无论你是想追更喜欢的游戏主播、科技评测UP主还是学习区的知识分享者这个工具都能帮你把“被动等待”变成“主动推送”。它的部署方式非常灵活你可以选择在本地电脑上运行也可以把它丢到服务器上通过Cron定时任务实现7x24小时不间断监控甚至用Docker封装实现一键部署。接下来我会详细拆解这个项目的设计思路、实现细节、部署踩坑经验以及如何根据你的需求进行定制化改造。2. 核心设计与架构思路2.1 为什么选择“轮询”而非“订阅”在设计之初我首先考虑的是实现机制。对于内容更新监控常见的思路有两种一是轮询Polling即定期主动去查询目标状态二是订阅Subscription即等待目标主动推送通知。B站本身并没有为普通用户提供官方的UP主更新推送API因此“订阅”这条路基本走不通。虽然有一些第三方服务或通过抓取动态RSS的方式但稳定性和可控性较差。因此轮询成为了最可靠、最可控的方案。它的原理就像你设定一个闹钟每隔一段时间就去所有关注的UP主空间“逛一圈”看看有没有新发布的视频。这种方案的优点非常明显实现简单不依赖任何不稳定的第三方服务或未公开的接口所有逻辑都掌握在自己手里。当然它的缺点是需要消耗一定的网络请求资源并且存在一个“时间窗口”延迟——即UP主发布视频后需要等到下一次轮询检查时才会被发现。不过对于非实时的视频更新通知来说这个延迟例如设置为每小时或每6小时检查一次是完全可接受的。2.2 技术栈选型与考量确定了轮询机制后就需要选择具体的技术组件。我的选型原则是轻量、高效、稳定、易于维护。核心请求库bilibili-api-python直接使用B站官方API是最规范的方式但官方API文档复杂且部分接口有鉴权要求。bilibili-api-python这个第三方库完美解决了这个问题。它封装了B站的各种API包括获取用户投稿视频列表并且内置了请求签名和风控逻辑。这意味着我们不需要自己去研究B站那套复杂的Wbi签名算法也不用担心因为请求格式不对而被拦截大大降低了开发成本和维护风险。这是本项目能稳定运行的基础。异步HTTP客户端aiohttp由于我们需要同时查询多个UP主的状态如果使用同步请求如requests库那么查询第2个UP主时必须等待第1个的请求完成效率极低。aiohttp配合Python的asyncio异步框架可以让我们并发地发起所有请求。假设监控20个UP主使用异步请求的总耗时约等于其中最慢的那个请求的耗时而不是20个请求耗时的总和。这对于提升检查速度、减少资源占用至关重要。数据持久化JSON文件我们需要记录每个UP主最新视频的信息以便下次检查时进行对比。这里没有选择数据库如SQLite而是使用了简单的JSON文件。原因在于数据结构非常简单UID - 最新视频信息读写频率很低仅每次检查时读写一次数据量也很小。使用JSON文件避免了引入额外的数据库依赖使得项目更加轻量部署也更简单。data/monitor_data.json就是这个“记忆中枢”。通知渠道SMTP邮件通知方式有很多选择如微信机器人、Telegram Bot、Server酱等。我最终选择了最通用、最稳定的SMTP邮件。几乎每个人都有邮箱且邮件服务非常可靠。通过配置发件邮箱的SMTP服务我们可以实现跨平台、无需安装特定App的通知。邮件的富文本格式也能很好地展示视频标题、链接、播放量等信息用户体验不错。2.3 整体工作流程整个工具的运行时序可以概括为以下几步形成了一个清晰的闭环启动加载配置文件config.py中的UP主列表和邮箱设置。读取历史从data/monitor_data.json读取上次检查时记录的每个UP主的最新视频信息。并发查询使用asyncio和aiohttp并发地向B站API请求当前UP主的最新视频列表。对比分析将API返回的最新视频与本地记录的历史最新视频进行对比。识别新视频如果发现新的视频通过视频BVID或发布时间判断则将其加入“新视频列表”。发送通知如果本次检查发现了新视频则通过SMTP协议将包含新视频详情的汇总邮件发送到指定邮箱。更新记录无论是否有新视频都将本次查询到的最新视频信息更新到本地JSON文件中作为下一次检查的基准。定时触发通过Cron或系统定时任务在设定的时间点自动重复步骤1-7。这个流程确保了状态的持续跟踪和变更的及时通知逻辑清晰且健壮。3. 核心模块深度解析与配置要点3.1 配置文件详解config.py是你的控制中心config.py是整个项目的大脑所有自定义行为都在这里控制。它主要包含两大块UP主列表和邮件配置。UP_LIST 配置的艺术UP_LIST { 68559: 22和33, 403748305: BML制作指挥部, # 你的UID: 你给TA的备注名, }UID获取很多人分不清UID和房间号。UID是用户数字ID永久不变。在UP主空间页的网址https://space.bilibili.com/12345678中12345678就是UID。房间号如7777是直播用的不能用于此API。命名建议值如22和33是你自定义的显示名会出现在日志和邮件里。建议起一个你一眼就能认出的名字特别是当UP主昵称特殊或经常更改时一个好记的备注名非常有用。排序无关字典的键值对顺序不影响检查顺序因为查询是并发进行的。注意添加UP主时请务必确认UID正确。一个快速验证的方法是将UID填入https://api.bilibili.com/x/space/acc/info?midUID这个链接在浏览器中打开如果能返回JSON数据且包含正确的用户名则UID有效。EMAIL_CONFIG 的避坑指南邮件配置是新手最容易出错的地方。以下是一个完整的QQ邮箱配置示例EMAIL_CONFIG { smtp_host: smtp.qq.com, smtp_port: 587, # 关键QQ邮箱常用TLS端口是587 smtp_user: 123456qq.com, # 你的QQ邮箱 smtp_pass: abcdefghijklmnop, # 这里是授权码不是密码 to: [your_notificationemail.com] # 接收邮箱 }smtp_port端口不对是连接失败的首要原因。587端口通常用于STARTTLS先明文连接再升级加密465端口用于SSL/TLS一上来就加密连接。大多数现代邮件客户端和库推荐使用587。如果587不行可以尝试465但代码中可能需要调整SSL上下文创建方式。smtp_pass这是最大的坑这里填的不是你的邮箱登录密码而是“授权码”。以QQ邮箱为例你需要登录网页版QQ邮箱在“设置”-“账户”中找到“POP3/IMAP/SMTP服务”并开启根据提示生成一个16位的授权码。使用授权码是为了在不暴露主密码的前提下授权第三方应用发信更安全。to列表可以添加多个邮箱地址这样你和你的小伙伴都能收到通知。例如“to”: [“meqq.com”, “friendgmail.com”]。3.2 监控主逻辑monitor.py如何工作monitor.py是项目的心脏其内部逻辑值得仔细剖析。异步并发获取视频列表核心函数fetch_up_videos利用asyncio.gather并发执行所有UP主的查询任务。async def fetch_up_videos(up_list): async with aiohttp.ClientSession() as session: tasks [] for uid, name in up_list.items(): # 为每个UP主创建一个异步任务 task asyncio.create_task(get_latest_video(session, uid, name)) tasks.append(task) # 等待所有任务完成 results await asyncio.gather(*tasks, return_exceptionsTrue) return results这里有一个关键细节return_exceptionsTrue。这意味着即使某个UP主的查询任务失败了比如网络波动或UP主账号异常也不会导致整个程序崩溃而是会将异常对象作为结果返回。后续处理中需要判断结果是否为异常并进行容错处理保证其他UP主的正常监控不受影响。新旧视频对比策略如何准确判断一个视频是“新”的这里采用了双重校验策略非常稳健BVID比对BVID如BV1xx411c7mh是B站视频的唯一标识符。如果本地记录的最新视频BVID与API返回的最新视频BVID不同则判定为新视频。这是最直接、最可靠的判断。发布时间比对将API返回的最新视频的发布时间戳与本地记录的时间戳进行比较。如果API返回的时间更晚即使BVID因某些极端原因如视频被删除无法匹配也能通过时间判断出新视频的存在。 这种“主键比对时间戳兜底”的策略极大地增强了程序的鲁棒性。邮件内容生成与格式化生成一封信息丰富、排版清晰的邮件是提升体验的关键。代码中构建了一个纯文本格式的邮件正文但通过使用特殊符号如 、、和等号分隔线在邮件客户端中也能呈现出清晰的结构。email_body f B站 UP 主更新汇总 检查时间{check_time} 本次更新{len(new_videos_list)} 个 监控 UP 主{len(up_list)} 个 新视频列表 for item in new_videos_list: email_body f {item[index]}. 【{item[up_name]}】 {item[title]} {item[url]} 发布时间{item[pubdate]} ⏱️ 时长{item[duration]} ️ 播放量{item[view]} 实操心得纯文本邮件兼容性最好但如果你想更美观可以考虑使用HTML格式。不过要注意某些邮箱客户端或企业邮箱可能会过滤或限制HTML邮件中的样式。保持简洁、信息优先是最稳妥的方案。4. 从零开始的完整部署与运维指南4.1 本地环境部署开发与测试对于初学者或在本地长期使用推荐此方式便于调试和修改。环境准备确保你的电脑已安装Python 3.8或更高版本。在终端输入python3 --version或python --version确认。获取代码使用Git克隆项目是最佳方式便于后续更新。git clone https://github.com/Artistkisa/bilibili-up-update-tracker.git cd bilibili-up-update-tracker如果不用Git也可以直接下载ZIP压缩包并解压。安装依赖项目根目录下的requirements.txt列出了所有必需的Python库。pip install -r requirements.txt注意如果遇到权限问题可以尝试pip install --user -r requirements.txt。在国内如果下载速度慢可以使用清华镜像源pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple。配置按照上文详解仔细编辑src/config.py文件填入你的UP主UID和邮箱信息。首次运行测试cd src python monitor.py首次运行会创建data/和logs/目录并在data/下生成monitor_data.json文件记录当前UP主的最新视频状态。首次运行不会发邮件因为还没有“旧状态”可供对比。这是正常现象。4.2 服务器部署与Cron定时任务要让脚本在后台自动、定期运行部署到Linux服务器并配置Cron是最经典和稳定的方案。步骤一将项目上传至服务器你可以使用scp命令或SFTP工具如FileZilla将整个项目文件夹上传到你的服务器例如放到/home/yourname/bilibili-tracker目录下。步骤二在服务器上安装依赖通过SSH连接到你的服务器进入项目目录安装依赖。建议使用Python虚拟环境venv来隔离项目环境避免污染系统Python。cd /home/yourname/bilibili-tracker python3 -m venv venv # 创建虚拟环境 source venv/bin/activate # 激活虚拟环境 pip install -r requirements.txt激活虚拟环境后终端的命令提示符前通常会出现(venv)字样。步骤三配置Cron定时任务Cron是Linux系统的定时任务管理器。我们来设置一个每天上午10点自动检查的任务。# 1. 编辑当前用户的cron配置 crontab -e如果你是第一次使用可能会让你选择编辑器选择熟悉的如nano即可。2. 在打开的编辑器中添加一行# 每天上午10点整运行一次 0 10 * * * cd /home/yourname/bilibili-tracker/src /home/yourname/bilibili-tracker/venv/bin/python monitor.py /home/yourname/bilibili-tracker/logs/cron.log 21这条命令需要仔细解读0 10 * * *Cron时间表达式表示“每天的第10小时的第0分钟”即每天10:00 AM。cd .../src先切换到脚本所在目录。/home/.../venv/bin/python这是关键这里必须使用虚拟环境下的Python解释器绝对路径而不是简单的python。因为Cron有自己的运行环境默认找不到你激活的虚拟环境。使用绝对路径确保脚本能使用安装好依赖的Python环境。monitor.py运行主脚本。 .../logs/cron.log 21将脚本的标准输出stdout和标准错误stderr都重定向追加到cron.log文件中。21表示将错误输出合并到标准输出流。这非常重要便于日后排查问题。3. 保存并退出编辑器在nano中是按CtrlX然后按Y确认再按回车。验证Cron是否生效# 查看当前用户的所有Cron任务 crontab -l # 查看Cron日志Ubuntu/Debian系统通常在这里 tail -f /var/log/syslog | grep CRON # 或者查看我们指定的日志文件 tail -f /home/yourname/bilibili-tracker/logs/cron.log如果配置正确在设定的时间点你就能在日志文件中看到脚本的运行输出了。4.3 使用Docker容器化部署Docker提供了极致的环境一致性和便捷性特别适合在云服务器或NAS上部署。步骤一构建Docker镜像在项目根目录包含Dockerfile的目录执行docker build -t bilibili-tracker:latest .这个命令会根据Dockerfile中的指令如基于Python镜像、复制代码、安装依赖构建一个名为bilibili-tracker的本地镜像。步骤二准备持久化配置和数据Docker容器是无状态的重启后容器内的文件更改会丢失。因此我们需要将配置文件和数据目录“映射”到宿主机上。在宿主机上找一个目录例如/opt/bilibili-tracker。将项目中的src/config.py复制到/opt/bilibili-tracker/下并按需修改。在/opt/bilibili-tracker/下创建data和logs空文件夹用于持久化数据。步骤三运行容器docker run -d \ --name bilibili-tracker \ -v /opt/bilibili-tracker/config.py:/app/src/config.py \ -v /opt/bilibili-tracker/data:/app/data \ -v /opt/bilibili-tracker/logs:/app/logs \ bilibili-tracker:latest \ python /app/src/monitor.py-d后台运行。--name给容器起个名字。-v进行目录映射挂载卷。左边是宿主机路径右边是容器内路径。这样容器内对配置和数据的读写实际上都发生在宿主机上容器重启也不会丢失。最后的命令是容器启动后要执行的命令这里直接运行一次监控脚本。步骤四设置容器内Cron进阶上面的命令只运行一次脚本。要实现定时运行有两种方式宿主机Cron调用容器在宿主机Cron中配置任务定时执行docker exec命令。# 在宿主机 crontab -e 中添加 0 10 * * * docker exec bilibili-tracker python /app/src/monitor.py容器内安装Cron修改Dockerfile在镜像中安装cron服务并将Cron配置和启动脚本打包进去。这种方式更自包含但镜像会稍大且调试更复杂。对于新手推荐第一种方式逻辑更清晰。5. 高级技巧、问题排查与经验分享5.1 性能优化与大规模监控当监控的UP主数量非常多例如超过100个时需要考虑一些优化策略。调整并发量asyncio默认的并发连接数很高但向同一个域名api.bilibili.com发起过多并发请求可能会被B站服务器短暂限制。可以在创建aiohttp.ClientSession时使用Connector限制并发数。import aiohttp from aiohttp import TCPConnector connector TCPConnector(limit20) # 限制同时最多20个连接 async with aiohttp.ClientSession(connectorconnector) as session: # ... 你的代码将limit设置为一个合理的数值如10-30既能保证速度又显得更“友好”。分批次检查如果UP主数量极大可以考虑将他们分成多个列表用不同的Cron任务在不同的时间点检查不同的列表将请求压力平摊开。减少请求数据量bilibili-api-python的get_videos方法默认可能获取较多的视频。如果只关心最新视频可以查看库的文档看是否支持参数只获取最近的一条投稿以减少返回的数据量。5.2 常见问题排查手册这里汇总了部署和使用过程中最常见的问题及解决方法。问题现象可能原因排查步骤与解决方案运行脚本后无任何输出直接退出1. Python路径或依赖问题。2. 脚本存在语法错误。1. 在命令行显式使用python3 monitor.py。2. 在脚本开头加import traceback用try...except包裹主函数并打印traceback.format_exc()查看详细错误。首次运行后data/monitor_data.json文件为空或未创建1. 对data/目录没有写入权限。2. 获取UP主视频列表的API请求全部失败。1. 检查data/目录是否存在手动创建并确保当前用户有写权限 (chmod 755 data)。2. 检查网络并尝试在代码中打印API请求的返回结果或异常信息。邮件发送失败提示认证错误1. 邮箱密码/授权码错误。2. SMTP端口或服务器地址错误。3. 邮箱未开启SMTP服务。1.反复确认smtp_pass是授权码不是登录密码。2. 核对smtp_port(587/465) 和smtp_host。3. 登录网页版邮箱在设置中确认POP3/SMTP服务已开启。邮件发送失败提示连接超时或被拒绝1. 服务器防火墙/网络策略阻止了出站SMTP连接。2. 使用了错误的加密方式。1. 尝试在服务器上使用telnet smtp.qq.com 587测试端口连通性。如果不通联系服务器提供商或检查安全组规则。2. 尝试将端口从587改为465并确保代码中创建SMTP连接时使用了SSL上下文如果库支持。Cron任务没有执行1. Cron命令语法错误或路径错误。2. 环境变量问题导致python命令找不到。3. Cron日志未正确捕获输出。1. 使用crontab -l检查命令。务必使用绝对路径特别是Python解释器路径。2. 在Cron命令中可以手动设置环境变量或在脚本顶部使用#!/usr/bin/env python3并给脚本加执行权限。3. 检查Cron日志 (/var/log/syslog或journalctl -u cron) 和自定义的日志文件cron.log看是否有错误信息。监控不到新视频但UP主明明更新了1. 本地缓存文件 (monitor_data.json) 数据异常或损坏。2. UP主的UID填写错误。3. B站API返回数据格式有变化。1. 删除monitor_data.json文件让脚本重新初始化所有UP主状态。2. 再次核对UID。3. 运行脚本时增加日志输出打印API返回的原始数据检查是否还能正确解析出视频信息。5.3 扩展思路让通知更符合你的习惯邮件通知虽然通用但你可能更习惯其他即时通讯工具。这里提供几个改造方向集成Server酱微信通知Server酱提供了简单的HTTP API可以将消息推送到微信。你可以在monitor.py中在发送邮件的逻辑旁边添加一个函数当发现新视频时调用Server酱的API。import requests def send_to_wechat(sckey, title, content): url fhttps://sctapi.ftqq.com/{sckey}.send data {title: title, desp: content} requests.post(url, datadata)将你的SendKey配置到config.py在发送邮件后调用此函数即可。集成Telegram BotTelegram Bot的API也非常友好。你需要先通过BotFather创建一个Bot获取Token和你的Chat ID。然后使用python-telegram-bot库或直接通过requests调用Telegram Bot API发送消息。自定义邮件模板如果你觉得纯文本邮件不够美观可以修改邮件生成部分的代码使用email.mime.text和email.mime.multipart创建HTML格式的邮件嵌入更丰富的样式和图片。增加去重逻辑有时UP主可能会对视频进行重新编辑或替换导致BVID不变但内容更新。目前的策略基于BVID不会重复通知。如果你希望捕获这种“更新”事件可以额外对比视频的修改时间戳或MD5值如果API提供但这会复杂很多且B站API通常不提供这些信息。这个项目麻雀虽小五脏俱全。它涉及了异步编程、API调用、数据持久化、邮件服务和自动化部署等多个实用知识点。希望这份超详细的解析和指南不仅能帮你顺利部署使用这个工具更能让你理解其背后的设计逻辑从而能够根据自己的需求进行定制和扩展。