基于 Sync your cookie + Cloudflare KV + MCP + Claude 实现 B站视频信息自动获取

📖 前言

在现代 Web 开发中,我们经常需要从各种平台获取数据。本文将分享我如何构建一个 B站视频信息获取工具,这个项目不仅仅是一个简单的爬虫,而是一个集成了多项前沿技术的完整解决方案:

  • Sync your cookie: 谷歌插件
  • Cloudflare KV: 全球分布式键值存储
  • MCP (Model Context Protocol): AI 模型上下文协议
  • Claude AI: 强大的 AI 编程助手

本项目的独特之处在于通过 Chrome 扩展自动同步加密的 Cookie 到云端,然后通过 Python 程序自动解密并获取所需的视频信息。

🎯 项目概述

核心功能

  • 🔐 从 Cloudflare KV 自动获取并解密 Cookie 数据
  • 🎬 批量获取 B站视频详细信息(标题、播放量、点赞数等)
  • 📊 支持多种输出格式(控制台、JSON、CSV)
  • 🌐 基于 MCP 协议获取最新的 bilibili-api 文档
  • 🚀 异步处理,高效稳定

技术架构图

graph TB A[Chrome扩展] --> B[加密Cookie数据] B --> C[Cloudflare KV存储] C --> D[Python获取工具] D --> E[多层解密] E --> F[提取B站凭证] F --> G[bilibili-api调用] G --> H[视频信息输出] I[MCP协议] --> J[Claude AI] J --> K[最新API文档] K --> G style C fill:#f9f,stroke:#333,stroke-width:2px style J fill:#9f9,stroke:#333,stroke-width:2px style E fill:#ff9,stroke:#333,stroke-width:2px

作用

Sync your cookie 是一个 Chrome 扩展程序,它可以帮助您将 Cookie 同步到 Cloudflare。它是一个有用的工具,用于在不同设备之间共享 Cookie, 免去了登录流程的烦恼,此外也提供了cookie管理面板查看,管理已经过同步的 cookie。

🌐 Cloudflare KV:全球分布式存储利器

什么是 Cloudflare KV?

Cloudflare Workers KV 是一个全球分布式键值存储服务,具有以下特点:

  1. 全球分发: 数据自动复制到全球 200+ 个数据中心
  2. 超低延迟: 边缘计算节点就近响应
  3. 高可用性: 99.9% 的服务可用性保证
  4. 简单易用: RESTful API,支持各种编程语言

在本项目中的应用

class CloudflareKVClient:
    """Cloudflare KV 存储客户端"""
    
    def __init__(self, account_id, namespace_id, api_token):
        self.account_id = account_id
        self.namespace_id = namespace_id  
        self.api_token = api_token
        self.base_url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/storage/kv/namespaces/{namespace_id}"
        self.headers = {
            "Authorization": f"Bearer {api_token}",
            "Content-Type": "application/json"
        }
    
    def get_value(self, key):
        """从KV存储获取值"""
        try:
            url = f"{self.base_url}/values/{key}"
            response = requests.get(url, headers=self.headers, timeout=10)
            response.raise_for_status()
            
            # 检查响应内容类型
            content_type = response.headers.get('content-type', '')
            
            if 'application/json' in content_type:
                return response.json()
            else:
                # 返回加密的Cookie数据
                return response.text.strip()
                
        except Exception as e:
            print(f"❌ 获取Cloudflare KV数据失败: {e}")
            return None

配置示例

{
  "cloudflare_kv": {
    "account_id": "your-account-id",
    "namespace_id": "your-namespace-id",
    "api_token": "your-api-token",
    "key_name": "sync-your-cookie"
  }
}

🤖 MCP:AI 时代的新协议

MCP (Model Context Protocol) 简介

MCP 是 Anthropic 推出的一种新协议,用于 AI 模型与外部工具和数据源的标准化交互。它解决了以下问题:

  1. 上下文管理: 为 AI 模型提供结构化的上下文信息
  2. 工具集成: 标准化的工具调用接口
  3. 数据访问: 安全可控的外部数据获取

在 Claude 中使用 MCP

在我的项目中,我使用 MCP 的 Context7 服务获取最新的 bilibili-api 文档:

# 通过 MCP 获取 bilibili-api 最新文档
# 这确保了我们使用的是最新的API接口和最佳实践

from bilibili_api import video, Credential, sync

# 根据 MCP 文档,创建 Video 对象的正确方式
v = video.Video(bvid=bvid, credential=self.credential)

# 根据 MCP 文档,获取视频信息的正确方法
info = await v.get_info()

MCP 的优势

  1. 实时更新: 获取最新的 API 文档和最佳实践
  2. 准确性: 避免过时信息导致的错误
  3. 效率: 直接获取相关文档片段,提高开发效率

🔐 多层加密解密:安全与效率的平衡

加密流程解析

先将Sync your cookie项目clone到本地,然后通过claude解析代码,从中得到Sync your cookie的加密cookie方法,然后得到对应的解密方法,本地测试

Chrome 扩展将 Cookie 数据进行多层加密后存储到 Cloudflare KV:

原始Cookie数据 → Protocol Buffers → zlib压缩 → gzip压缩 → Base64编码 → 存储

解密实现

def decrypt_cookie_data(self, encrypted_data):
    """解密Cookie数据"""
    if not encrypted_data or not encrypted_data.strip():
        print("❌ 加密数据为空")
        return None
    
    try:
        print("🔍 开始解密Cookie数据...")
        
        # 步骤1: Base64 解码
        buffer = base64.b64decode(encrypted_data.strip())
        print(f"✅ Base64 解码成功,数据大小: {len(buffer)} 字节")
        
        # 步骤2: gzip 解压缩
        buffer = gzip.decompress(buffer)
        print(f"✅ gzip 解压缩成功,数据大小: {len(buffer)} 字节")
        
        # 步骤3: zlib 解压缩
        buffer = zlib.decompress(buffer)
        print(f"✅ zlib 解压缩成功,数据大小: {len(buffer)} 字节")
        
        # 步骤4: protobuf 解析
        cookies_map = cookie_pb2.CookiesMap()
        cookies_map.ParseFromString(buffer)
        print("✅ protobuf 解析成功")
        
        return cookies_map
        
    except Exception as e:
        print(f"❌ 解密失败: {str(e)}")
        return None

Protocol Buffers 结构

// cookie.proto
syntax = "proto3";

message Cookie {
  string name = 1;
  string value = 2;
  string domain = 3;
  string path = 4;
  int64 expires = 5;
  bool httpOnly = 6;
  bool secure = 7;
  string sameSite = 8;
}

message DomainCookie {
  repeated Cookie cookies = 1;
}

message CookiesMap {
  map<string, DomainCookie> domainCookieMap = 1;
}

凭证提取

def extract_bilibili_credentials(self, cookies_map):
    """从解密的Cookie数据中提取B站登录凭证"""
    if not cookies_map:
        return None
        
    credentials = {}
    
    # 查找B站相关域名的Cookie
    bilibili_domains = ['.bilibili.com', 'bilibili.com', '.www.bilibili.com']
    
    for domain, domain_cookie in cookies_map.domainCookieMap.items():
        if any(bili_domain in domain for bili_domain in bilibili_domains):
            print(f"🔍 检查域名: {domain}")
            
            for cookie in domain_cookie.cookies:
                if cookie.name == 'SESSDATA':
                    credentials['SESSDATA'] = cookie.value
                    print(f"✅ 找到 SESSDATA")
                elif cookie.name == 'bili_jct':
                    credentials['BILI_JCT'] = cookie.value
                    print(f"✅ 找到 BILI_JCT")
                elif cookie.name == 'buvid3':
                    credentials['BUVID3'] = cookie.value
                    print(f"✅ 找到 BUVID3")
    
    return credentials if credentials else None

🎬 B站 API 集成:数据获取的艺术

bilibili-api 的选择

经过对比测试,最终选择了 bilibili-api 库的 9.1.0 版本:

  • ✅ 稳定可靠的接口封装
  • ✅ 完善的异步支持
  • ✅ 丰富的功能覆盖
  • ✅ 活跃的社区维护

核心获取逻辑

async def get_video_info_async(self, video_input):
    """异步获取视频信息"""
    # 获取凭证
    if not self.credential:
        if not self.get_credentials_from_kv():
            print("⚠️ 未获取到登录凭证,将尝试无登录访问")
    
    # 提取BV号
    bvid = self.extract_bvid(video_input)
    if not bvid:
        print(f"❌ 无法从输入中提取有效的BV号: {video_input}")
        return None
    
    try:
        print(f"🔍 正在获取视频信息: {bvid}")
        
        # 创建 Video 对象
        v = video.Video(bvid=bvid, credential=self.credential)
        
        # 获取视频信息
        info = await v.get_info()
        
        # 从 info 中提取统计信息
        stat = info.get('stat', {})
        
        # 构造返回数据
        result = {
            'title': info.get('title', ''),
            'bvid': bvid,
            'aid': info.get('aid', 0),
            'url': f"https://www.bilibili.com/video/{bvid}",
            'view_count': stat.get('view', 0),
            'like_count': stat.get('like', 0),
            'coin_count': stat.get('coin', 0),
            'favorite_count': stat.get('favorite', 0),
            'uploader': info.get('owner', {}).get('name', ''),
            'upload_time': datetime.fromtimestamp(info.get('pubdate', 0)).strftime('%Y-%m-%d %H:%M:%S'),
            # ... 更多字段
        }
        
        return result
        
    except Exception as e:
        print(f"❌ 获取视频信息失败: {e}")
        return None

BV号提取逻辑

def extract_bvid(self, input_str):
    """从输入中提取BV号"""
    # 如果直接是BV号
    if input_str.startswith('BV') and len(input_str) == 12:
        return input_str
    
    # 如果是完整链接,提取BV号
    bv_pattern = r'BV[1-9a-km-z]{10}'
    match = re.search(bv_pattern, input_str, re.IGNORECASE)
    if match:
        return match.group(0)
    
    return None

📊 数据输出:多样化的展示方式

控制台输出

def format_console_output(self, data):
    """格式化控制台输出"""
    print("\n" + "="*70)
    print("🎬 B站视频信息 (基于 MCP bilibili-api)")
    print("="*70)
    print(f"标题: {data['title']}")
    print(f"BV号: {data['bvid']}")
    print(f"链接: {data['url']}")
    print(f"播放数: {data['view_count']:,}")
    print(f"点赞数: {data['like_count']:,}")
    print(f"UP主: {data['uploader']}")
    print("="*70)

CSV 输出(中文表头)

def save_csv(self, data, output_path):
    """保存为CSV格式"""
    # 中文表头
    chinese_headers = [
        '标题', 'BV号', 'AV号', '链接', '分区', '分区ID', '分P数', '版权类型',
        '播放数', '点赞数', '投币数', '收藏数', '分享数', '评论数', '弹幕数', 
        'UP主', 'UP主UID', '上传时间', '时长(秒)', '简介', '封面图'
    ]
    
    with open(output_path, 'w', newline='', encoding='utf-8') as f:
        writer = csv.writer(f)
        writer.writerow(chinese_headers)
        # 写入数据...

🛠️ 开发环境与依赖管理

Python 环境选择

选择 conda py310 环境的原因:

  1. 兼容性: Python 3.10 对 asyncio 有更好的支持
  2. 稳定性: 避免系统 Python 环境污染
  3. 依赖管理: conda 更好的包版本管理
# 环境创建和激活
conda create -n py310 python=3.10
conda activate py310

# 依赖安装
pip install -r requirements.txt

关键依赖版本

requests==2.32.4
bilibili-api==9.1.0
aiohttp==3.7.4.post0
beautifulsoup4==4.9.3
protobuf>=3.19.0

🔄 完整的工作流程

// Chrome扩展将Cookie加密后上传到Cloudflare KV
const encryptedData = encryptCookies(cookies);
await uploadToCloudflareKV(encryptedData);

2. Python 程序获取并解密

# 从 KV 获取加密数据
encrypted_data = kv_client.get_value('sync-your-cookie')

# 多层解密
cookies_map = kv_client.decrypt_cookie_data(encrypted_data)

# 提取 B站凭证
credentials = kv_client.extract_bilibili_credentials(cookies_map)

3. 视频信息获取

# 创建认证对象
credential = Credential(
    sessdata=credentials['SESSDATA'],
    bili_jct=credentials['BILI_JCT'],
    buvid3=credentials['BUVID3']
)

# 获取视频信息
video_info = await get_video_info_async(bv_id)

4. 数据输出

# 多种输出格式
save_json(video_info, 'output.json')
save_csv(video_info, 'output.csv')
format_console_output(video_info)

📈 性能优化与最佳实践

异步处理

# 使用 asyncio 提高并发性能
async def batch_get_videos(self, video_list):
    tasks = []
    for video_id in video_list:
        tasks.append(self.get_video_info_async(video_id))
    
    results = await asyncio.gather(*tasks, return_exceptions=True)
    return results

错误处理

# 完善的错误处理机制
try:
    video_info = await self.get_video_info_async(bv_id)
except aiohttp.ClientError as e:
    print(f"❌ 网络请求失败: {e}")
except json.JSONDecodeError as e:
    print(f"❌ JSON 解析失败: {e}")
except Exception as e:
    print(f"❌ 未知错误: {e}")

缓存策略

# 简单的内存缓存
from functools import lru_cache

@lru_cache(maxsize=100)
def get_video_cached(self, bv_id):
    return self.get_video_info(bv_id)

🚀 使用示例

基本用法

# 测试工具
python video_info_fetcher_mcp.py --test

# 获取单个视频信息
python video_info_fetcher_mcp.py BV1uv411q7Mv

# 输出到 CSV
python video_info_fetcher_mcp.py BV1uv411q7Mv --format csv

实际运行效果

✅ bilibili-api 库加载成功
✅ protobuf 模块加载成功
🔍 正在从KV获取密钥: sync-your-cookie
🔍 开始解密Cookie数据...
✅ Base64 解码成功,数据大小: 1395 字节
✅ gzip 解压缩成功,数据大小: 1372 字节
✅ zlib 解压缩成功,数据大小: 3325 字节
✅ protobuf 解析成功
✅ 找到 SESSDATA
✅ 找到 BILI_JCT
✅ 找到 BUVID3
✅ 成功提取到 3 个B站登录凭证
✅ 成功创建 Credential 对象
🔍 正在获取视频信息: BV1uv411q7Mv
✅ 成功获取视频信息

======================================================================
🎬 B站视频信息 (基于 MCP bilibili-api)
======================================================================
标题: 爆肝98小时!在MC中还原糖调小镇
BV号: BV1uv411q7Mv
播放数: 19,676
点赞数: 2,250
UP主: -星の忆-
======================================================================

🔮 未来展望

功能扩展

  1. 批量处理: 支持从文件批量读取视频列表
  2. 数据分析: 添加视频数据分析和可视化功能
  3. 实时监控: 定时获取关注UP主的最新视频
  4. 多平台支持: 扩展到其他视频平台

技术优化

  1. 分布式处理: 使用 Celery 实现分布式任务队列
  2. 数据库存储: 集成 PostgreSQL 或 MongoDB
  3. API 服务: 提供 RESTful API 接口
  4. Docker 部署: 容器化部署方案

💡 总结与思考

这个项目展示了如何将多项现代技术有机结合:

  1. 云服务集成: Cloudflare KV 提供全球分布式存储
  2. AI 辅助开发: MCP + Claude 提升开发效率
  3. 安全加密: 多层加密保护敏感数据
  4. 异步编程: 提高程序性能和用户体验

通过这个项目,我深刻体会到:

  • 技术选型的重要性: 合适的技术栈能事半功倍
  • 安全性考虑: 数据加密和权限控制至关重要
  • 用户体验: 简洁的接口和清晰的输出同样重要
  • 可扩展性: 良好的架构设计为未来发展奠定基础

希望这个项目和分享能为大家在类似的技术探索中提供一些参考和启发!


📚 参考资料

🔗 项目地址

posted @ 2025-08-02 18:33  陈科科  阅读(53)  评论(0)    收藏  举报