零依赖Python实现B站自动签到:Cookie驱动与API调用实战
1. 项目概述与核心价值如果你是一个B站深度用户每天手动完成登录、看视频、分享、投币这些日常任务来获取经验值或者为了支持喜欢的主播需要去他的直播间发送弹幕签到时间一长这绝对会变成一件枯燥又容易忘记的“负担”。我自己就经历过这个阶段直到我决定用代码把这件事自动化。今天要分享的就是基于XiaoYiWeio/bili-checkin这个项目思路我构建的一套零依赖、纯Python标准库实现的B站全自动签到与任务系统。它完美解决了两个核心痛点一是每日65点经验值的自动获取二是直播间弹幕签到的无人值守执行。这个工具的核心设计哲学是“极简与高效”。它不依赖任何第三方HTTP请求库如requests也不使用笨重的浏览器自动化工具如Selenium仅仅通过Python内置的urllib模块配合你从浏览器获取的一次性登录CookieSESSDATA和bili_jct就能模拟真人操作调用B站官方的内部API。这意味着它的运行速度极快资源占用极低并且因为去除了复杂的依赖部署和迁移变得异常简单。无论是放在自己的树莓派、NAS上还是利用云服务器的定时任务都能稳定可靠地运行。对于想要快速提升B站等级的用户、需要维护多个账号的UP主助手、或是单纯想用技术解放双手的开发者来说这个方案提供了一个清晰、可复现的路径。接下来我会从设计思路、核心原理、到每一步的实操细节包括如何安全地获取Cookie、如何解析API、以及如何避开那些我踩过的坑为你完整拆解这个项目。你会发现用不到200行Python代码就能构建一个属于自己的自动化小助手。2. 核心设计思路与架构解析2.1 为什么选择“零依赖”与“Cookie驱动”方案在开始动手之前方案选型至关重要。市面上常见的自动化方案主要有两类一是基于Selenium或Playwright的浏览器模拟二是基于requests或aiohttp的直接API调用。我最终选择了后者并且更进一步连requests这样的第三方库都舍弃了原因如下。首先浏览器模拟方案虽然直观能执行几乎所有用户操作但其缺点非常明显资源消耗大需要启动一个完整的浏览器进程、运行速度慢、对环境依赖强需要匹配的浏览器驱动并且极其不稳定——B站前端页面结构稍有变动脚本就可能失效。这对于需要7x24小时稳定运行的后台任务来说是不可接受的。其次基于第三方库的API调用是更优的选择但引入requests库仍然增加了一个外部依赖。对于追求极致简洁和可移植性的项目我希望它能在任何有Python标准环境的地方“开箱即用”无需pip install。Python 3.4 内置的urllib.request和json库已经完全足够处理HTTP请求和JSON解析。那么如何实现登录认证呢这就是“Cookie驱动”的精髓。我们不需要模拟登录过程那需要处理验证码、加密密码等复杂问题。我们只需要让用户在浏览器中正常登录一次B站然后从浏览器的开发者工具中提取出关键的登录态Cookie——主要是SESSDATA和bili_jct。这两个Cookie值包含了服务器认可的会话信息和CSRF令牌。只要在后续的API请求中携带它们B站服务器就会认为这是“已登录用户”发出的合法请求。这种方法将复杂的登录逻辑交给了用户和浏览器脚本只负责最纯粹的“任务执行”大大降低了复杂度和维护成本。注意Cookie是有有效期的通常为1个月左右。这意味着你需要定期约每月一次重新登录并更新Cookie文件。这是此方案的一个小小代价但相比其带来的稳定性和简便性是完全值得的。2.2 项目架构与模块职责基于以上思路项目的目录结构非常清晰每个脚本各司其职bili-checkin/ ├── scripts/ │ ├── daily.py # 核心执行每日经验任务登录、观看、分享、投币、直播签到 │ ├── checkin.py # 核心执行直播间弹幕签到并包含Cookie管理功能 │ └── lookup.py # 工具将UP主名称、UID、空间链接等解析为直播间房间号room_id ├── SKILL.md # 用于集成到OpenClaw AI助手的技能定义文件 └── persona.md # 定义AI助手与用户交互的对话人格checkin.py是这个项目的基础。它承担了两个核心功能Cookie管理提供了--save-cookie参数允许用户将提取的SESSDATA和bili_jct加密后保存到本地文件~/.bili_cookie并设置严格的文件权限600确保只有用户自己可读。直播间签到接收房间号room_id和自定义弹幕内容通过调用B站直播间的发送弹幕API完成签到并返回亲密度和经验值奖励信息。daily.py是主要的任务执行器。它按顺序调用四个B站经验任务API登录任务模拟一次客户端登录触发每日登录经验。观看任务通过API“报告”观看了一个视频通常是一个固定的、无需真实播放的视频ID。分享任务通过API“报告”分享了一个视频。投币任务这是经验值的大头每天最多投5枚硬币可获得50经验。脚本会自动从账号余额中投出5枚硬币。考虑到硬币的珍贵性脚本贴心地提供了--skip-coin参数允许用户跳过此步骤。直播签到实际上它会内部调用checkin.py的逻辑向一个默认的或指定的直播间发送签到弹幕。lookup.py是一个实用的辅助工具。B站的直播间签到需要的是数字房间号room_id但用户通常只知道UP主的名字、个人空间链接或直播链接。这个脚本通过一系列网络请求将这些信息解析为最终的room_id极大提升了工具的易用性。这种模块化设计使得代码逻辑清晰易于维护和扩展。例如未来如果想增加“银瓜子兑换”或“漫画签到”等功能只需在daily.py中添加相应的函数模块即可。3. 环境准备与一次性配置详解3.1 获取核心身份凭证SESSDATA 与 bili_jct这是整个流程中唯一需要手动操作的步骤也是最重要的一步。请严格按照以下步骤在Chrome或Edge浏览器内核相同中操作正常登录打开 bilibili.com 输入账号密码完成登录。确保登录成功能正常浏览个人动态。打开开发者工具在B站任意页面按下键盘上的F12键或右键点击页面选择“检查”。定位到Cookies在开发者工具顶部切换到“Application”标签页中文可能是“应用程序”。在左侧侧边栏找到“Storage” - “Cookies”并点击其下展开的https://www.bilibili.com。查找目标Cookie在右侧会列出该域名下所有的Cookie。你需要找到名为SESSDATA和bili_jct的两行。SESSDATA一串很长的、包含百分号%的字符串这是你的会话数据。bili_jct一串较短的、由字母和数字组成的字符串这是用于防止跨站请求伪造CSRF的令牌。复制值分别双击这两个Cookie的“Value”字段完整地复制它们的值。请务必小心不要复制到多余的空格或换行符。实操心得SESSDATA的值通常以%开头和结尾中间包含很多%2A之类的编码字符复制时要确保完整。一个验证方法是复制出来的字符串长度通常在200字符以上。bili_jct则短得多像一个普通的令牌字符串。3.2 安全保存Cookie到本地获取到Cookie后绝不能以明文形式写在脚本里或到处粘贴。我们使用项目提供的checkin.py脚本将其安全地保存到你的用户主目录下的一个隐藏文件中。打开终端Linux/macOS或命令提示符/PowerShellWindows进入你克隆的项目目录bili-checkin/scripts/。运行以下命令将YOUR_SESSDATA和YOUR_BILI_JCT替换为你刚才复制的实际值python3 checkin.py --save-cookie --sessdata 你的SESSDATA长字符串 --bili-jct 你的bili_jct字符串这个命令背后做了什么脚本会在你的家目录~下创建一个名为.bili_cookie的隐藏文件。它将SESSDATA和bili_jct以keyvalue的格式写入文件。最关键的一步它会调用系统命令将文件权限设置为600即仅文件所有者可读可写其他用户无任何权限。这是保护你账号安全的重要措施防止其他用户或进程窃取你的登录态。执行成功后通常会看到类似Cookie saved to /home/your_username/.bili_cookie的提示。至此一次性配置完成。后续所有脚本运行时都会自动从这个文件中读取Cookie无需再次输入。4. 核心功能实操与代码逐行解析4.1 直播间弹幕签到 (checkin.py)这是最基础的功能模块。我们来看其核心函数send_danmaku是如何工作的。# 示例代码结构非完整代码 import urllib.request import urllib.parse import json import os def load_cookie(): 从 ~/.bili_cookie 文件加载Cookie cookie_file os.path.expanduser(~/.bili_cookie) if not os.path.exists(cookie_file): raise FileNotFoundError(Cookie文件未找到请先运行 --save-cookie 命令) cookies {} with open(cookie_file, r) as f: for line in f: if in line: key, value line.strip().split(, 1) cookies[key] value return cookies.get(SESSDATA), cookies.get(bili_jct) def send_danmaku(room_id, msg签到): 向指定直播间发送弹幕 sessdata, csrf load_cookie() # csrf 即 bili_jct if not all([sessdata, csrf]): print(错误Cookie信息不完整) return # 1. 构建API请求URL和参数 url https://api.live.bilibili.com/msg/send # 弹幕发送API需要表单格式的数据 data urllib.parse.urlencode({ color: 16777215, # 默认白色 fontsize: 25, # 标准字体大小 mode: 1, # 滚动弹幕 msg: msg, # 弹幕内容 rnd: int(time.time()), # 随机数防重复 roomid: room_id, # 直播间ID bubble: 0, csrf: csrf, # 关键的CSRF令牌 csrf_token: csrf, }).encode(utf-8) # 2. 构建请求头携带Cookie headers { Content-Type: application/x-www-form-urlencoded, Cookie: fSESSDATA{sessdata}, User-Agent: Mozilla/5.0 ..., # 模拟浏览器UA Referer: fhttps://live.bilibili.com/{room_id}, # 重要表明请求来源 Origin: https://live.bilibili.com, } # 3. 使用urllib发送POST请求 req urllib.request.Request(url, datadata, headersheaders) try: with urllib.request.urlopen(req) as response: result json.loads(response.read().decode(utf-8)) # 4. 解析响应 if result.get(code) 0: print(f弹幕发送成功{msg}) # 响应中通常包含亲密度变化信息 data result.get(data, {}) print(f亲密度{data.get( intimacy, 0)} 经验值{data.get(exp, 0)}) else: print(f弹幕发送失败{result.get(message)}) except urllib.error.URLError as e: print(f网络请求失败{e.reason})关键点解析CSRF防护B站的所有写操作发送弹幕、投币、分享都需要验证csrf即bili_jct参数它必须与Cookie中的bili_jct值一致这是防止跨站请求伪造的重要机制。我们的脚本从同一个源获取这两个值保证了其一致性。请求头HeadersUser-Agent模拟了真实浏览器Referer和Origin头对于通过B站服务器的反爬虫检查至关重要缺少它们可能导致403错误。错误处理代码包含了基本的网络错误URLError和API错误code ! 0处理。在实际使用中你可能需要根据不同的错误码如“弹幕发送过于频繁”添加重试逻辑或延迟。4.2 每日经验任务全自动执行 (daily.py)daily.py脚本是任务编排的中心。它按顺序调用各个任务函数。我们以“投币任务”为例看看如何安全地消耗硬币。def coin_task(csrf, sessdata): 执行投币任务默认投5枚 url https://api.bilibili.com/x/web-interface/coin/add # 需要投币的视频ID这里通常选择一个固定的、允许投币的视频 target_aid 170001 # 示例视频实际可能需要一个长期有效的视频 headers { /* 类似上述的headers包含Cookie和csrf */ } coins_to_add 5 success_count 0 for i in range(coins_to_add): data urllib.parse.urlencode({ aid: target_aid, multiply: 1, # 每次投1枚 select_like: 1, # 同时点赞 cross_domain: true, csrf: csrf }).encode() req urllib.request.Request(url, datadata, headersheaders, methodPOST) try: with urllib.request.urlopen(req) as resp: result json.load(resp) if result[code] 0: success_count 1 print(f投币成功 ({i1}/5)) else: # 处理错误硬币不足、重复投币等 print(f投币失败{result[message]}) break except Exception as e: print(f投币请求异常{e}) break time.sleep(1) # 关键每次投币间隔1秒避免触发频率限制 print(f投币任务完成成功投出 {success_count} 枚硬币预计获得 {success_count * 10} 经验) return success_count注意事项与心得目标视频选择脚本需要指定一个视频IDaid进行投币。选择一个官方、长期存在且允许投币的视频至关重要。如果视频被删除或UP主关闭了投币功能任务就会失败。在实际项目中这个target_aid可能需要定期维护或提供一个可配置的选项。频率限制B站对投币操作有频率限制。代码中的time.sleep(1)是必须的快速连续请求会导致操作被拒绝。甚至1秒间隔有时也可能触发限制在实际运行中我建议增加到2-3秒更为稳妥。硬币余额检查当前脚本没有在投币前检查账户硬币余额。如果硬币不足API会返回错误。一个更健壮的实现应该先调用账户信息API查询硬币余额再决定投币数量。--skip-coin参数这个参数非常实用。对于硬币稀缺的用户或者只想完成登录、观看、分享等“零成本”任务时可以使用此参数跳过投币步骤。4.3 UP主信息查找与房间号解析 (lookup.py)这个工具脚本极大地提升了易用性。其原理是通过B站开放的搜索API和网页解析将多种输入统一为直播间房间号room_id。def resolve_to_room_id(identifier): 解析输入返回room_id。 输入可以是房间号、UP主名、UID、空间链接、直播链接。 # 情况1输入本身就是纯数字假设为room_id if identifier.isdigit(): # 可以额外请求API验证该room_id是否存在 return identifier # 情况2输入是直播链接如 https://live.bilibili.com/22605245 if live.bilibili.com in identifier: # 使用正则表达式从URL中提取数字 import re match re.search(rlive\.bilibili\.com/(\d), identifier) if match: return match.group(1) # 情况3输入是空间链接或UID如 https://space.bilibili.com/123456 或 “123456” # 情况4输入是UP主名称如 “老番茄” # 对于情况3和4流程更复杂 # a. 如果是UID或空间链接提取出数字UID。 # b. 如果是名称使用搜索API https://api.bilibili.com/x/web-interface/search/type 搜索用户获取第一个结果的UID。 # c. 拿到UID后请求 https://api.bilibili.com/x/space/acc/info?mid{UID} 获取用户信息。 # d. 从用户信息JSON中找到 live_room 对象下的 roomid 字段。 # e. 如果 live_room 为空说明该UP主未开通直播间。 # 这里省略具体代码展示逻辑链条 uid extract_uid(identifier) # 提取或搜索得到UID user_info get_user_info_by_uid(uid) # 请求用户信息API room_id user_info.get(data, {}).get(live_room, {}).get(roomid) if room_id: return str(room_id) else: raise ValueError(f未找到用户 {identifier} 的直播间信息)通过这个解析器用户就可以使用非常自然的方式指定签到目标python3 lookup.py “老番茄” python3 lookup.py 22605245 python3 lookup.py https://live.bilibili.com/22605245脚本会自动输出对应的room_id这个room_id可以直接用于checkin.py的--room参数。5. 部署方案与自动化运行指南让脚本每天自动运行才能真正解放双手。这里提供几种常见的部署方案。5.1 方案一Linux/macOS 系统的 Crontab最经典Crontab是类Unix系统上最常用的定时任务工具。假设你的脚本位于/home/user/bili-checkin/scripts。打开当前用户的crontab编辑界面crontab -e添加定时任务在文件末尾添加一行。以下例子设定每天上午10点15分执行每日任务并在晚上8点30分为指定主播进行直播间签到。# 分 时 日 月 周 命令 15 10 * * * cd /home/user/bili-checkin/scripts /usr/bin/python3 daily.py /tmp/bili_daily.log 21 30 20 * * * cd /home/user/bili-checkin/scripts /usr/bin/python3 checkin.py --room 22605245 --msg “晚安打卡” /tmp/bili_live.log 21cd /path/to/scripts确保在正确的目录下执行以便脚本能找到相对路径的模块或配置文件。/usr/bin/python3使用绝对路径指定Python解释器避免因环境变量问题找不到命令。 /tmp/bili_daily.log 21将脚本的标准输出和标准错误都重定向追加到日志文件中方便后续查看执行结果和排查问题。/tmp目录下的文件重启可能会消失如需持久化请改为~/bili.log等路径。保存并退出在vim中按Esc后输入:wq。Cron服务会自动加载新配置。实操心得Cron的时间语法容易出错。一个在线工具 crontab.guru 可以帮助你快速验证和生成cron表达式。另外Cron的环境变量非常精简可能不包含你终端里的PATH这就是为什么强调要使用绝对路径的原因。5.2 方案二Windows 系统的任务计划程序对于Windows用户可以通过图形化的“任务计划程序”来实现。搜索并打开“任务计划程序”。点击右侧“创建基本任务”。填写名称和描述例如“B站每日签到”。触发器选择“每天”并设置具体时间。操作选择“启动程序”。“程序或脚本”填写C:\Python39\python.exe你的Python安装路径。“添加参数”填写D:\path\to\bili-checkin\scripts\daily.py你的脚本绝对路径。“起始于”填写D:\path\to\bili-checkin\scripts脚本所在目录。完成创建后可以在右侧手动“运行”一次进行测试。5.3 方案三使用云服务器或容器如果你有常开的云服务器如腾讯云、阿里云的轻量应用服务器或者在家里的NAS如群晖DSM上运行Docker部署起来更为方便。云服务器通过SSH连接到服务器按照方案一的步骤配置Crontab即可。优势是网络稳定24小时在线。Docker容器你可以编写一个简单的Dockerfile将脚本和Cookie文件通过卷挂载或构建时复制打包进镜像然后使用docker run配合--restartalways和cron服务在容器内运行定时任务。这种方式隔离性好易于迁移。通用建议无论采用哪种部署方式务必先手动运行几次脚本确保一切正常再加入到定时任务中。同时配置日志记录如上文中的 logfile是排查问题的生命线。6. 常见问题排查与进阶技巧即使脚本设计得再完善在实际运行中也可能遇到各种问题。这里记录了我遇到的一些典型情况及其解决方法。6.1 Cookie失效问题现象脚本突然开始报错提示“未登录”或“权限错误”错误码可能是-101、-111等。原因与解决自然过期SESSDATA的默认有效期大约为30天。到期后需要重新登录B站网页版并按照3.1节的步骤获取新的Cookie值然后重新运行python3 checkin.py --save-cookie ...命令更新本地文件。异地登录或异常行为如果你的账号在别处登录或者B站检测到异常活动可能会使当前Cookie失效。同样需要重新获取。文件权限或损坏检查~/.bili_cookie文件是否存在权限是否为600内容格式是否正确SESSDATAxxx和bili_jctyyy各占一行。自动化提醒思路可以写一个简单的检查脚本定期比如每周一次调用一个需要登录态的API如查询账户信息如果返回未登录错误则通过邮件、Server酱或Telegram Bot发送提醒通知你更新Cookie。6.2 网络请求失败或返回403错误现象脚本执行失败提示URLError或HTTP Error 403: Forbidden。原因与解决User-Agent被识别B站可能会屏蔽一些简单的Python UA。确保你的请求头中User-Agent是一个常见的浏览器UA字符串可以从你自己的浏览器开发者工具中复制一个。缺少Referer或Origin头如4.1节所述对于发送弹幕、投币等POST请求Referer和Origin头是强校验的必须正确设置。IP频率限制如果你在短时间内发送了大量请求比如快速循环投币可能会触发B站的临时IP限制。解决方案是在关键操作如投币、发送弹幕之间增加足够的延迟time.sleep(2)或更长。代理问题如果你身处需要特殊网络环境的地区确保运行脚本的机器网络通畅。脚本本身不支持配置代理如果需要可以设置全局代理或修改代码使用urllib.request.ProxyHandler。6.3 任务执行不完整或经验未增加现象脚本运行显示成功但B站APP或网页上经验值没有变化或者某些任务如分享没完成。原因与解决API变更B站的后端API可能会升级或改动。虽然核心API相对稳定但仍有小概率发生变化。关注脚本运行日志如果某个任务持续失败可以手动在浏览器中抓包F12 - Network查看完成任务时调用的真实API地址和参数与脚本中的进行对比更新。视频ID失效每日任务中的“观看”和“分享”通常针对一个固定的视频ID。如果这个视频被删除任务就会失败。需要更新脚本中的aid参数。你可以手动找一个B站官方的、长期存在的视频比如“每日动画”用其aid替换。投币任务硬币不足或重复投币前最好先查询余额。另外B站规定每个视频最多投2枚硬币。如果脚本一直对同一个视频投币投到第3枚时会失败。更健壮的逻辑是准备一个视频ID列表轮流投币。6.4 进阶技巧多账号管理与安全增强多账号支持你可以创建多个Cookie文件例如.bili_cookie_account1和.bili_cookie_account2。然后修改load_cookie()函数使其接受一个账号标识参数读取对应的文件。在定时任务中为每个账号分别设置一个Cron任务使用不同的Cookie文件路径。环境变量配置将Cookie值或文件路径通过环境变量传入而不是硬编码在脚本或命令行中安全性更高。例如export BILI_SESSDATAyour_sessdata export BILI_JCTyour_jct python3 daily.py然后在脚本中使用os.environ.get(BILI_SESSDATA)读取。加入随机延迟与随机话术让自动化行为更接近真人。在定时任务触发时间上加入随机分钟数偏移在发送的弹幕内容中从一个预定义的列表如“打卡”、“来了”、“签到”、“报道”中随机选择可以进一步降低被系统识别为机器人的风险。这个项目麻雀虽小五脏俱全。它不仅仅是一个签到脚本更是一个理解Web自动化、API调用、Cookie机制和定时任务部署的绝佳实践。通过亲手配置和解决运行中遇到的问题你能对网络编程和系统运维有更深的体会。最重要的是它真的能帮你省下每天几分钟的重复操作让科技服务于生活。