1. 为什么需要获取B站视频的AID和CID作为一个经常分析B站视频数据的技术爱好者我发现AID和CID这两个参数在数据抓取中特别重要。AIDArchive ID是B站给每个视频分配的唯一标识符相当于视频的身份证号。而CIDContent ID则是视频内容的实际标识特别是在获取视频流或弹幕时必不可少。举个例子如果你想开发一个B站视频数据分析工具或者想批量下载某个UP主的视频内容就必须先获取这些ID。我去年做过一个项目需要统计某UP主所有视频的播放量变化趋势就是靠爬取AID和CID实现的。当时遇到的最大问题是很多教程只讲基础爬虫却没说明这两个关键参数的关系和获取方法。2. 环境准备和基础配置2.1 安装必要的Python库在开始之前我们需要准备好Python环境。我推荐使用Python 3.7及以上版本因为有些新的异步特性会很有帮助。以下是必须安装的库pip install requests pip install beautifulsoup4 pip install lxmlrequests库用于发送HTTP请求beautifulsoup4和lxml则用来解析HTML内容。我建议同时安装这两个解析器因为在实际使用中有些页面用lxml解析更快而有些则用html.parser更稳定。2.2 了解B站的API结构B站实际上提供了很多公开的API接口虽然官方文档不完整但通过浏览器开发者工具可以观察到。我花了些时间研究发现以下几个关键API用户信息APIhttps://api.bilibili.com/x/space/acc/info?mid{uid}视频列表APIhttps://api.bilibili.com/x/space/arc/search?mid{uid}pn1ps25视频详情APIhttps://api.bilibili.com/x/player/pagelist?aid{aid}其中mid是用户的UIDpn是页码ps是每页数量aid就是我们要找的视频AID。3. 获取UP主视频列表的完整流程3.1 第一步通过UP主UID获取基本信息首先我们需要获取UP主的UID。这个可以在UP主主页的URL中找到比如主页URL是https://space.bilibili.com/123456那么123456就是UID。import requests import json def get_up_info(uid): url fhttps://api.bilibili.com/x/space/acc/info?mid{uid} headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } response requests.get(url, headersheaders) data json.loads(response.text) return data[data]这个函数会返回UP主的基本信息包括昵称、签名、粉丝数等。我在实际使用中发现一定要设置User-Agent头否则可能会被B站拒绝请求。3.2 第二步获取UP主的全部视频列表获取视频列表稍微复杂些因为B站的API是分页的。我们需要循环请求直到获取所有视频def get_all_videos(uid): base_url fhttps://api.bilibili.com/x/space/arc/search?mid{uid} headers {User-Agent: Mozilla/5.0...} all_videos [] page 1 while True: url f{base_url}pn{page}ps50 # 每页50条 response requests.get(url, headersheaders) data json.loads(response.text) if not data[data][list][vlist]: break all_videos.extend(data[data][list][vlist]) page 1 return all_videos这里有几个需要注意的点ps参数控制每页数量最大可以设为50当vlist为空时说明已经获取完所有视频建议在每次请求间添加短暂延迟避免触发反爬机制4. 从AID到CID的详细解析4.1 理解AID和CID的关系很多刚开始接触B站API的朋友会困惑AID和CID的区别。简单来说AID是视频的唯一标识在视频URL中就能看到如www.bilibili.com/video/av170001CID是视频内容的标识一个AID可能对应多个CID比如分P视频在我的项目中曾经遇到过一个视频有多个CID的情况这时候需要特别注意处理。4.2 获取视频CID的代码实现有了AID后获取CID就相对简单了def get_cid(aid): url fhttps://api.bilibili.com/x/player/pagelist?aid{aid} headers {User-Agent: Mozilla/5.0...} response requests.get(url, headersheaders) data json.loads(response.text) if data[data]: return data[data][0][cid] # 取第一个CID return None对于分P视频data[data]会包含多个元素每个元素对应一个分P的CID。在我的使用经验中90%的情况只需要第一个CID就够了。5. 实战中的常见问题与解决方案5.1 反爬机制应对策略B站有一定的反爬措施我遇到过以下几种情况请求频率过高被暂时封禁缺少必要请求头被拒绝需要登录才能获取的数据解决方案在请求间添加随机延迟0.5-2秒完善请求头至少包含User-Agent和Referer对于需要登录的接口可以模拟登录获取cookieimport time import random def safe_request(url): time.sleep(random.uniform(0.5, 1.5)) headers { User-Agent: Mozilla/5.0..., Referer: https://www.bilibili.com } return requests.get(url, headersheaders)5.2 数据存储与后续处理获取到AID和CID后通常会需要存储起来供后续分析。我推荐使用SQLite或MySQLimport sqlite3 def init_db(): conn sqlite3.connect(bilibili.db) c conn.cursor() c.execute(CREATE TABLE IF NOT EXISTS videos (aid INTEGER PRIMARY KEY, cid INTEGER, title TEXT)) conn.commit() return conn def save_video(conn, aid, cid, title): c conn.cursor() c.execute(INSERT OR IGNORE INTO videos VALUES (?, ?, ?), (aid, cid, title)) conn.commit()这种结构化存储方式便于后续的统计分析比如计算平均播放量、找出最受欢迎的视频等。6. 进阶应用场景6.1 视频数据分析有了AID和CID我们可以做很多有趣的分析。比如分析UP主视频发布时间规律统计视频播放量与弹幕数的关系追踪视频热度随时间的变化我曾经用这些数据帮一个UP主朋友分析出他的最佳发布时间是晚上8-10点调整后播放量提升了30%。6.2 构建个人视频档案库对于喜欢的UP主可以用这个技术建立本地视频档案记录视频元信息标题、发布时间等实时播放量、弹幕数视频封面和简介这样即使视频被删除也能保留基本信息。我建议每周自动运行一次爬虫更新数据。7. 完整代码示例下面是一个整合了所有功能的完整示例import requests import json import time import random import sqlite3 class BiliSpider: def __init__(self): self.headers { User-Agent: Mozilla/5.0..., Referer: https://www.bilibili.com } self.conn sqlite3.connect(bilibili.db) self.init_db() def init_db(self): c self.conn.cursor() c.execute(CREATE TABLE IF NOT EXISTS videos (aid INTEGER PRIMARY KEY, cid INTEGER, title TEXT)) self.conn.commit() def safe_request(self, url): time.sleep(random.uniform(0.5, 1.5)) return requests.get(url, headersself.headers) def get_up_info(self, uid): url fhttps://api.bilibili.com/x/space/acc/info?mid{uid} response self.safe_request(url) return json.loads(response.text)[data] def get_all_videos(self, uid): base_url fhttps://api.bilibili.com/x/space/arc/search?mid{uid} all_videos [] page 1 while True: url f{base_url}pn{page}ps50 response self.safe_request(url) data json.loads(response.text) if not data[data][list][vlist]: break all_videos.extend(data[data][list][vlist]) page 1 return all_videos def get_cid(self, aid): url fhttps://api.bilibili.com/x/player/pagelist?aid{aid} response self.safe_request(url) data json.loads(response.text) return data[data][0][cid] if data[data] else None def save_video(self, aid, cid, title): c self.conn.cursor() c.execute(INSERT OR IGNORE INTO videos VALUES (?, ?, ?), (aid, cid, title)) self.conn.commit() def run(self, uid): up_info self.get_up_info(uid) print(f开始获取UP主 {up_info[name]} 的视频数据...) videos self.get_all_videos(uid) print(f共找到 {len(videos)} 个视频) for video in videos: aid video[aid] cid self.get_cid(aid) self.save_video(aid, cid, video[title]) print(f已保存: {video[title]} (AID: {aid}, CID: {cid})) self.conn.close() if __name__ __main__: spider BiliSpider() spider.run(2026561407) # 替换为目标UP主的UID这个类封装了所有功能使用时只需创建实例并传入UP主UID即可。我在实际项目中还添加了异常处理和日志记录建议你也这样做。