Python自动化实战:从零搭建B站个人机器人robotbilibili

发布时间:2026/8/27 19:46:20
Python自动化实战:从零搭建B站个人机器人robotbilibili robotbilibili 这个名字听起来像是“B站机器人”的英文连写。实际上也确实是我给自己一组自动化脚本起的代号用 Python 处理每天在 B站重复操作的几件事比如签到、监听直播弹幕、关键词自动回复、定时任务提醒。它不是一个官方产品也不是拉下来就能一键跑的现成项目而是我在搭这个名为 robotbilibili 的个人工具时整理出来的一套可复现流程和踩坑记录。如果你正在做个人账号运营、直播弹幕互动测试或者单纯想学 Python 自动化这篇文章会比较适合。最值得先看的不是功能列表而是它在普通机器上能不能稳定跑起来以及遇到登录失效、WebSocket 掉线、批量任务失败时该怎么从日志和配置里定位问题。下面按我实际落地的顺序拆一遍。1. 先别急着写代码搞清楚 robotbilibili 到底要解决什么问题1.1 它是机器人不是爬虫也不是外挂开始写 robotbilibili 之前我先把它的定位想得很清楚它是一个“帮你执行重复操作”的机器人不是帮你获取平台不公开数据的爬虫也不是绕过平台规则的外挂。这个定位决定了后面所有设计。它能解决的是那些每天固定要做的、逻辑简单但很占用时间的事情。比如打开 B站首页检查今天有没有签到。看到某个直播间开播自动进入挂一会儿时长。在直播间里监听弹幕当出现指定关键词时回复一句欢迎语或提示。每天固定时间检查任务列表把结果写到日志里。这些操作本身不复杂复杂的是每天都做。人的精力有限偶尔还会忘记。robotbilibili 的价值就是把“重复执行”这件事接管过来让我只需要在配置里改规则不用每次都打开浏览器手动点。这个边界很重要。一旦把机器人定义成“越强越好”就很容易往采集、批量操作、绕过限制的方向走。那样不仅维护成本高账号风险也很大。我更建议把范围限制在“自己账号能正常访问的功能”和“低频率的个人自动化”上。1.2 先想清楚要支持哪些场景搭 robotbilibili 的时候我给自己列了一个需求清单按优先级排序优先级场景输入输出P0每日签到账号登录态签到结果日志P0直播间弹幕监听房间号或直播间短ID弹幕消息记录P1关键词自动回复房间号 关键词规则自动发送弹幕P1定时任务提醒定时表达式通知消息P2多账号支持多份账号配置独立日志和结果P2Web 管理面板浏览器访问启停任务、查看日志开始不要贪多。我最早只想做一个“能监听弹幕并回复关键词”的机器人后来发现没有签到任务队列就没有稳定的长期运行场景。于是先把签到做成最小可用模块再把弹幕监听接进来最后才补定时任务。如果你现在准备自己做同样的事我的建议是先选一个最简单的单任务跑通比如“读取配置里的账号做一次签到请求把结果写入日志”。这一步通了后面所有模块都只是在这个基础上加功能。2. 环境准备为什么我建议先用 Python 配置文件搭起来2.1 运行环境与依赖robotbilibili 不需要 GPU也不需要很高的内存。我测试用的机器是 4 核 CPU、8GB 内存的普通环境跑签到、弹幕监听、定时任务都没有压力。如果你用 Windows 电脑或者 Linux 服务器都能正常跑唯一要注意的是文件路径和 Python 版本。我使用 Python 3.10 以上版本主要是为了用上更清晰的match和类型标注。依赖库也不用太多requests处理 HTTP 请求。websocket-client连接直播间的 WebSocket 弹幕协议。pyyaml读取配置文件。loguru日志输出比标准 logging 更容易看懂。apscheduler或croniter做定时调度。第一次搭环境不要一上来就装一堆框架。只需要能发请求、能连 WebSocket、能读配置、能写日志就够了。2.2 配置文件要拆开不要把参数硬编码到代码里我在早期版本里吃过亏把房间号、关键词、Cookie 都写在脚本顶部结果每次要改规则都要去改代码。后来我把它们全部拆到config.yaml里代码只负责读取和解释配置。一个参照结构如下account: cookie: 这里填你的登录凭证建议用环境变量读取 user_agent: Mozilla/5.0 ... behavior: enable_sign: true allow_auto_reply: true reply_interval_seconds: 15 tasks: sign: name: daily_sign cron: 0 9 * * * enabled: true live_listener: name: live_danmaku_listener room_id: 12345 keywords: - 你好 - 开始 log: level: INFO output_dir: logs这样做的原因有三个第一Cookie、房间号、关键词这些都是高频变更项应该放到配置里方便调整。第二代码和配置分离后你可以在不重新部署脚本的情况下修改机器人行为。第三多账号时只需要复制配置块不用复制代码。注意 Cookie 属于敏感信息不要直接提交到公开代码仓库。更稳妥的方式是把cookie放在环境变量里配置文件中只写占位符。2.3 日志和输出目录先规划好robotbilibili 跑起来之后最重要的不是代码本身而是日志。我一般会在项目根目录下建两个目录logs/存放运行日志。data/存放任务结果比如签到记录、弹幕记录、回复记录。日志文件名按日期拆分例如sign_20250101.log。任务结果可以写成 JSON Lines每一行是一条独立的 JSON 记录方便后续统计。{task: sign, time: 2025-01-01 09:00:01, status: ok, message: 签到成功} {task: sign, time: 2025-01-02 09:00:03, status: failed, message: cookie expired}如果没有日志脚本运行两小时后出现异常你很难判断是网络问题、参数问题还是调度问题。先规划好日志本身就是排查链路的一部分。3. 最小可运行链路登录态、请求、任务队列3.1 登录态管理Cookie 和安全边界robotbilibili 要操作个人账号必然需要登录态。我最早的做法是让脚本自动登录后来发现这样会引入验证码、风控判断、异地登录提醒等一系列问题反而更容易把账号弄出异常状态。更稳妥的做法是先手动在浏览器里登录自己的账号然后把浏览器中与登录态相关的凭证复制到配置文件里由requests.Session保持。下面是一个简化示例import requests import os session requests.Session() session.headers.update({ User-Agent: Mozilla/5.0 ..., Cookie: os.getenv(BILI_COOKIE, ), })这段代码只做了两件事创建 Session设置请求头。之后所有请求都复用同一个 Session能保留 Cookie避免每次请求都要重新带完整登录凭证。这里要特别说一句安全边界Cookie 等效于你账号的钥匙千万不能粘贴到公开仓库、笔记截图、聊天记录里。我一般会在本地建一个.env文件存放 Cookie并让代码从环境变量读取。.env文件必须加入.gitignore。3.2 跑通第一个接口任务先跑一个最简单的任务比如“获取当前登录用户的信息”。这个任务不涉及复杂参数只需要带登录态发一个请求然后判断返回结构。def fetch_user_info(session: requests.Session) - dict: url https://api.bilibili.com/x/web-interface/nav resp session.get(url, timeout5) data resp.json() if data.get(code) 0: return data.get(data, {}) raise RuntimeError(f接口返回错误: {data})上面这个接口地址是从公开资料里常见的示例具体字段名和地址要以你实际能调通的文档为准。重点是判断方式先看 HTTP 状态码再看接口返回的业务码最后才读数据。很多新手容易把“请求没有报错”当成“任务成功”。实际上接口可能返回了业务错误码只是脚本没有解析。所以第一个任务的验证标准应该是请求没有超时。返回的code为 0。日志里能看到用户昵称或 uid。如果失败日志里能清晰看到请求 URL、返回码和错误信息。3.3 任务队列设计为什么不要每个请求都开新线程跑通单次请求后很快会遇到批量任务。如果每个任务都创建新线程短时间涌入大量请求不仅自己机器负载高还可能触发对方的频控。robotbilibili 里我用了一个简单的任务队列一个线程往队列里放任务一个或几个 worker 线程从队列里取任务执行。核心优势是控制实际并发量。from queue import Queue from threading import Thread task_queue Queue() def worker(): while True: task task_queue.get() if task is None: break run_task(task) task_queue.task_done()为什么这样设计因为机器人本质上是“不断地把零散任务发给远端接口”如果不限制速率稳定的系统也会被搞得不稳定。队列把“要做什么”和“什么时候做”分开方便你后续加上延迟、重试和取消。我建议刚开始只启动 1 个 worker最多不要超过 3 个。个人账号场景下1 个 worker 已经足够唯一需要提高的是任务调度效率而不是并发数量。4. 弹幕与直播间消息机器人从监听开始4.1 WebSocket 连接和心跳robotbilibili 里比较有意思的模块是直播间弹幕监听。B站直播间的弹幕推送通常通过 WebSocket 完成先拿到真实房间 ID然后建立连接并持续发送心跳包。一个简化连接流程如下根据用户输入的短房间号请求直播间基础信息拿到真实room_id。使用websocket-client建立 WebSocket 连接。连接成功后按协议要求周期发送心跳包。收到消息后拆包、解析并写入日志。心跳包很关键。如果不发心跳连接会在几十秒内被服务端断开。很多掉线问题不是代码连不上而是忘记处理心跳或心跳间隔不对。我自己的做法是把心跳逻辑放到单独线程每 30 秒发送一次具体间隔以协议文档说明为准。下面展示一个连接骨架from websocket import WebSocketApp def on_open(ws): start_heartbeat(ws) def on_message(ws, message): handle_danmaku_message(message) def on_error(ws, error): logger.error(fWebSocket error: {error}) ws WebSocketApp( urlws_url, on_openon_open, on_messageon_message, on_erroron_error, ) ws.run_forever()这个示例只展示模块划分真实协议里每一个字段都需要按文档补全。不要直接把示例复制到生产环境。4.2 消息解析与关键词回复WebSocket 收到的数据一般不是纯文本可能是二进制或者有特定格式的帧。在写解析逻辑前我建议先做一件事把接收到的原始数据存到日志文件里观察规律再决定怎么解析。解析出弹幕内容后关键词匹配就简单了。规则放在配置里不要让代码写死。下面是一个示例思路def handle_danmaku_message(raw): data parse_message(raw) username data.get(username, ) content data.get(content, ) if match_keywords(content): send_reply(欢迎来到直播间~)这段代码很容易写真正难的是回复策略。如果直播间里人多你每匹配一条都回复很快就会刷屏。所以自动回复一定要加冷却时间和触发概率。4.3 自动回复的限频和语气控制我给 robotbilibili 设置的自动回复规则是两次回复间隔至少 15 秒。同一关键词在 60 秒内只回复一次。回复内容不涉及具体用户隐私也不发送诱导性消息。只回复公开弹幕中明确出现的关键词不做闲聊式自动对话。这些规则听起来保守但能显著降低账号被误判的风险。机器人回复弹幕本质上是在“代你说话”说多了容易引发反感。我见过有人把自动回复做到每条弹幕都秒回结果没过多久直播间管理员就把账号禁言了。更稳妥的做法是自动回复只承担“提示”“欢迎”“引导”的任务语气保持平和。比如用户输入“开始”机器人回复“正在处理稍等”用户输入“你好”机器人可以回复“欢迎来到直播间”。这类回复不容易出错。5. 从单任务到批量签到、抽奖提醒、粉丝牌等5.1 批量任务的成功标准不能只看“能否跑”单任务跑通后就要面对批量场景。robotbilibili 里最常见的批量任务有每日签到。多个直播间的弹幕监听。多个关键词规则的回复。定时提醒任务的调度。批量任务最忌讳的标准是“能不能跑”。你写一个 for 循环100 个任务全部执行如果没有报错就认为“成功”这是不够的。因为很多任务可能因为 Cookie 过期、参数错误、接口频控等原因静默失败了。我建议的验证维度是成功数状态为 ok 的任务数量。失败数状态为 failed 的任务数量。耗时整个批量任务从开始到结束的时间。卡住数超过预期时长仍未结束的任务数量。在日志里记录这些数据后你才能判断批量任务是否真的稳定。5.2 失败重试和错误码批量任务一定会遇到网络抖动。直接抛异常退出太粗暴不重试又会丢失任务。robotbilibili 里我按错误类型区分重试策略错误类型示例是否重试重试间隔网络超时read timeout是3 秒后重试业务失败code ! 0看情况不重试或重试 1 次登录失效cookie 过期否立即告警参数错误房间号不存在否不重试重试也不是无限重试。我设置了最多 3 次并且使用指数退避第一次间隔 3 秒第二次 6 秒第三次 12 秒。如果连续 3 次都失败就停止这个任务把错误写入单独的error.log并继续执行后续任务。5.3 输出结果一致性和校验批量任务运行完后还需要检查输出结果的一致性。比如多路弹幕监听A 直播间写入了日志B 直播间没有写入就说明 B 的连接可能有问题。我会在每个任务结束后写入一行 JSON 结果统一放到data/目录。每天跑一次汇总脚本校验当天任务记录是否完整。如果某一天签到任务没有执行日志里会清楚地显示“no task executed today”而不是让你去猜。校验还有一个好处能把“机器人跑没跑”变成“机器人执行了多少任务失败了多少”这对长期运行非常重要。6. 参数调整与稳定性判断6.1 并发、超时、重试的参数取舍机器人项目到了后期真正需要调的不是功能而是参数。robotbilibili 里我常调的参数有三类并发数个人项目建议 1 到 3。并发数越高单任务完成越快但失败率和封禁风险也会增加。不要一上来就开最大并发。超时时间连接超时我一般设置为 5 秒读取超时 10 秒。太短容易误判太长会在网络异常时把任务卡住。重试次数默认 3 次。重试次数太多会放大对接口的请求压力反而更容易触发频控。你可以先跑一个只有 10 条任务的测试观察总耗时和失败数。如果失败数超过 20%先不要加并发先看请求参数和 Cookie 是否正常。6.2 资源占用怎么看robotbilibili 长时间运行时资源占用也要关注。虽然它不需要 GPU但多路 WebSocket 连接、日志写入、定时调度都会消耗资源。我一般按这几个维度观察CPU正常情况下不会飙到 100%如果持续高可能是日志打印太频繁或解析逻辑有死循环。内存长时间运行会慢慢增长如果涨得厉害要检查是否每收到一条消息都创建了不必要的大对象。磁盘日志文件会越来越大建议按天拆分并定期清理 30 天前的日志。网络连接数多路 WebSocket HTTP 请求连接数很多。如果连接数持续上升要考虑连接释放问题。低配置机器可以跑单路弹幕监听但不要同时跑多个直播间的大流量解析。先把资源占用压到合理范围再考虑扩展功能。6.3 日志等级和追踪我习惯把日志等级分为三档开发时用 DEBUG日常运行用 INFO异常时看 ERROR。DEBUG 日志会打印原始数据包有助于理解协议但数量很大不适合长期开启。为了方便追踪每条日志都要带上任务标识。比如[sign]、[danmaku_1234]、[reply]。这样即使多个任务同时运行也能从日志里快速定位到对应任务。下面是一个日志输出示例2025-01-01 09:00:01 | INFO | [sign] 签到成功 2025-01-01 09:00:02 | WARNING | [danmaku_1234] 连接中断准备重连 2025-01-01 09:00:03 | ERROR | [sign] 签到失败cookie expired好的日志不是写给机器看的是写给人看的。排查问题时如果你能从日志里一眼看出“哪个任务、什么时间、什么状态”就已经解决了一半问题。7. 常见问题排查先看输入再看环境最后才改功能7.1 请求失败、登录失效、数据为空robotbilibili 跑久了最常见的是请求失败和数据为空。遇到这类问题我建议按下面的顺序排查先看返回的 HTTP 状态码。如果是 412、403多半是请求头或频控问题。再看接口业务码。很多 B站接口在返回 HTTP 200 的同时业务码会提示 cookie 失效。检查请求参数。比如房间号是否写成了短 ID 而没有转成真实 room_id。检查本机时间。时间偏差过大可能导致签名校验失败。最后检查代码逻辑看看是不是把参数名写错了。很多时候问题不在“代码能不能跑”而在“输入数据是不是干净”。数据为空时不要急着加异常捕获先打印原始返回体。原始返回体里通常有明确原因。7.2 WebSocket 掉线、心跳超时弹幕监听最烦的是断线重连。高频现象是连接建立后十几秒就断开日志里只有on_close。这时先看心跳有没有发出去。如果心跳没有发送服务端会认为你离线。排查顺序确认 WebSocket URL 是否正确。确认连接后是否启动了心跳线程。打印每一帧发送和接收的时间看是否有长时间未收到任何数据。检查网络稳定性尤其是长连接场景下的丢包。增加自动重连机制断开后等待 3 秒重新建立连接。重连不要无限制地连。比如连续失败 5 次后停止等到下一个循环再试。避免在远程接口已经在限流时本地还在疯狂重连。7.3 定时任务不执行或重复执行用了定时调度后还会遇到“没执行”和“重复执行”两种情况。没执行时先确认两件事一是时区二是 cron 表达式。很多调度库默认使用系统时区如果服务器是 UTC就会比北京时间晚 8 小时。重复执行多见于任务执行时间超过调度间隔。比如任务每 5 分钟触发一次但一次执行要 8 分钟结果上一次还没结束下一次又开始。解决方案是加单实例锁import threading task_lock threading.Lock() def schedule_task(name): if not task_lock.acquire(blockingFalse): logger.warning(f{name} 任务已在上一次执行跳过本次) return try: run_task(name) finally: task_lock.release()加锁后同一时间只会有一个任务实例在跑能避免很多重复执行的问题。8. 我建议的落地顺序和后续扩展方向8.1 先跑稳单任务再考虑复杂策略如果你也想搭一个类似 robotbilibili 的 B站机器人我建议按这个顺序来第一步手动登录写一个获取用户信息的脚本验证登录态可用。第二步实现一个签到任务把结果写入日志。第三步把签到任务挂到定时调度上跑一天看是否稳定。第四步接入 WebSocket 弹幕监听先只记录不自动回复。第五步加入关键词规则和自动回复严格控制回复频率。第六步优化日志、重试、并发参数补齐告警通知。每一步都有明确的验证标准不要跳步。跳步的后果是出了问题你分不清是登录态问题、网络问题还是调度问题。8.2 扩展多账号、Web 管理面板、消息推送跑稳定后可以考虑扩展。多账号对配置管理会有更高要求。每个账号单独一份配置日志和结果也要分目录。启动时统一加载运行时各账号任务隔离。Web 管理面板可以做成 Flask 或 FastAPI 应用提供任务启停、日志查看、配置修改功能。但要注意管理面板暴露在公网后安全风险会明显增加。如果只是本机使用只监听 127.0.0.1 就好。消息推送可以用邮件或 Server酱这类通知服务把任务失败、签到异常、长时间无心跳等情况推送到手机。推送规则不要太频繁否则会被通知轰炸。8.3 合规提醒最后再强调一次边界。robotbilibili 这类机器人本质上是帮你提高个人操作效率的工具不是用来突破平台限制的。使用时请记住只操作自己的账号不要批量操作他人账号。不采集、存储、传播他人隐私数据。不在弹幕区刷屏、发营销话术或诱导内容。遵守平台频控要求控制请求频率。不把 Cookie 等敏感信息提交到公开仓库。我个人更建议先把单任务跑稳再考虑批量和接口。robotbilibili 真正落地时最该盯住的不是功能列表而是输入格式、资源占用和失败重试。把这些基础打牢机器人才能从“能跑”变成“能长期稳定地跑”。