1. 项目概述:基于MCP协议的智能阅读网站开发实践
在AI技术快速发展的今天,如何将大型语言模型的能力有效整合到实际工作流中,是每个开发者都在思考的问题。最近我完成了一个智能阅读网站的MCP(模型上下文协议)实现,能够自动抓取B站视频内容并生成结构化摘要。这个项目很好地展示了如何通过MCP协议将AI能力转化为实际生产力工具。
这个智能阅读网站的核心功能包括:
- 自动爬取B站视频内容
- 智能解析视频字幕和音频
- 结构化内容提取与清洗
- 自动生成分层提纲和摘要
- 支持内容润色和简化
2. 技术架构设计与核心思路
2.1 MCP协议的核心价值
MCP(模型上下文协议)是一套标准化协议,它规范了模型如何安全地调用外部工具与访问资源。在这个项目中,MCP主要解决了以下几个关键问题:
- 工具集成标准化:通过统一接口集成B站API、必剪语音识别等不同服务
- 权限与安全控制:确保API调用在授权范围内进行
- 工作流编排:将内容获取、解析、处理等步骤串联成自动化流程
2.2 系统架构设计
整个系统采用模块化设计,主要包含以下组件:
code复制┌───────────────────────────────────────────────────────┐
│ 智能阅读网站MCP实现 │
├───────────────────┬───────────────────┬───────────────┤
│ 内容获取模块 │ 内容处理模块 │ 输出模块 │
├─────────┬─────────┼─────────┬─────────┼───────┬───────┤
│ B站搜索 │ 视频信息 │ 字幕解析 │ 音频转写 │ 结构化 │ 内容润 │
│ API工具 │ 获取工具 │ 工具 │ 工具 │ 输出 │ 色工具 │
└─────────┴─────────┴─────────┴─────────┴───────┴───────┘
3. 核心实现细节
3.1 内容获取模块实现
3.1.1 B站视频搜索功能
python复制@mcp.tool("search_video", description="搜索bilibili视频")
async def search_video(keyword: str, page: int = 1, page_size: int = 20) -> str:
"""
keyword: 搜索关键词
page: 页码,默认1
page_size: 每页数量,默认20
"""
search_result = await search.search_by_type(
keyword,
search_type=search.SearchObjectType.VIDEO,
page=page,
page_size=page_size
)
# 准备表格数据
table_data = []
headers = ["发布日期", "标题", "UP主", "时长", "播放量", "点赞数", "类别", "bvid"]
for video in search_result["result"]:
pubdate = datetime.fromtimestamp(video["pubdate"]).strftime("%Y/%m/%d")
title_link = f"[{video['title']}]({video['arcurl']})"
table_data.append([
pubdate,
title_link,
video["author"],
video["duration"],
video["play"],
video["like"],
video["typename"],
video["bvid"]
])
return tabulate(table_data, headers=headers, tablefmt="pipe")
关键点说明:
- 使用bilibili-api-python库的search_by_type方法进行视频搜索
- 搜索结果以Markdown表格形式返回,便于后续处理
- 包含视频基本信息(标题、作者、播放量等)和唯一标识bvid
3.1.2 视频信息获取
python复制@mcp.tool("get_video_info", description="获取bilibili视频信息,需提供视频BV号")
async def get_video_info(bvid: str) -> dict:
v = video.Video(bvid=bvid, credential=credential)
info = await v.get_info()
return info
3.2 内容处理模块实现
3.2.1 字幕获取与处理
python复制@mcp.tool("get_video_subtitle", description="获取bilibili视频的字幕,需提供视频BV号")
async def get_video_subtitle(bvid: str) -> dict:
v = video.Video(bvid=bvid, credential=credential)
cid = await v.get_cid(page_index=0)
info = await v.get_player_info(cid=cid)
json_files = info["subtitle"]["subtitles"]
# 查找AI生成的中文字幕
target_subtitle = None
for subtitle in json_files:
if subtitle["lan"] == "ai-zh" and subtitle["lan_doc"] == "中文(自动生成)":
target_subtitle = subtitle
break
if not target_subtitle:
# 检查视频时长,超过20分钟不处理
video_info = await v.get_info()
duration = video_info.get('duration', 0)
if duration > 1200: # 20分钟 = 1200秒
return "视频时长超过20分钟,无法生成实时字幕。"
# 获取音频URL进行语音识别
url_res = await v.get_download_url(cid=cid)
audio_arr = url_res.get('dash', {}).get('audio', [])
if not audio_arr:
return "没有找到AI生成的中文字幕"
audio = audio_arr[-1]
audio_url = ""
if '.mcdn.bilivideo.cn' in audio['baseUrl']:
audio_url = audio['baseUrl']
else:
backup_url = audio.get('backupUrl', [])
if backup_url and 'upos-sz' in backup_url[0]:
audio_url = audio['baseUrl']
else:
audio_url = backup_url[0] if backup_url else audio['baseUrl']
asr_data = get_audio_subtitle(audio_url)
return asr_data
# 处理已有字幕
subtitle_url = target_subtitle["subtitle_url"]
if not subtitle_url.startswith(('http://', 'https://')):
subtitle_url = f"https:{subtitle_url}"
async with aiohttp.ClientSession() as session:
async with session.get(subtitle_url) as response:
subtitle_content = await response.json()
if "body" in subtitle_content:
subtitle_text = "".join(item["content"] for item in subtitle_content["body"])
return subtitle_text
else:
return subtitle_content
处理逻辑说明:
- 优先获取视频已有的AI生成字幕
- 若无字幕,则检查视频时长(超过20分钟不处理)
- 获取视频音频流URL,使用必剪API进行语音识别
- 返回结构化字幕内容
3.2.2 必剪语音识别接口实现
python复制def get_audio_subtitle(url: str):
asr = BcutASR(file=url)
try:
task_id = asr.create_task()
while True:
task_resp = asr.result(task_id)
match task_resp.state:
case ResultStateEnum.ERROR:
return APIError(task_resp.code, task_resp.msg)
case ResultStateEnum.COMPLETE:
return task_resp.parse().to_txt()
time.sleep(5)
except Exception as e:
return APIError(400, str(e) or "获取音频字幕失败")
关键参数说明:
- API请求间隔:5秒(避免频繁请求)
- 音频格式支持:flac, aac, m4a, mp3, wav, mp4, m4s
- 输出格式:txt纯文本
4. 系统部署与配置
4.1 环境准备
- Python 3.8+环境
- 安装依赖库:
bash复制pip install -r requirements.txt
pip install tabulate pydantic
requirements.txt内容:
code复制mcp
bilibili-api-python
aiohttp
4.2 B站认证配置
需要从B站Cookie中获取以���三个参数:
- SESSDATA
- bili_jct
- buvid3
获取方法:
- 登录B站网站
- 按F12打开开发者工具
- 进入Application → Cookies → https://www.bilibili.com
- 查找对应的cookie值
环境变量设置(Windows):
cmd复制set sessdata=你的SESSDATA值
set bili_jct=你的bili_jct值
set buvid3=你的buvid3值
4.3 运行服务
bash复制python server.py
4.4 集成到MCP应用
在支持MCP的应用配置中添加:
json复制{
"mcpServers": {
"bilibili-mcp": {
"command": "python",
"args": [
"/path/to/server.py"
],
"env": {
"sessdata": "你的SESSDATA值",
"bili_jct": "你的bili_jct值",
"buvid3": "你的buvid3值"
}
}
}
}
5. 实际应用与优化建议
5.1 典型工作流程
-
内容获取阶段:
- 使用search_video工具搜索目标视频
- 通过bvid获取视频详细信息
-
内容处理阶段:
- 尝试获取现有字幕
- 若无字幕,则获取音频进行语音识别
- 对获取的文本进行清洗和结构化
-
输出阶段:
- 生成分层提纲
- 可选的内容润色和简化
5.2 性能优化建议
-
缓存机制:
- 对已处理的视频结果进行缓存
- 设置合理的缓存过期时间(如1天)
-
请求限流:
- 实现令牌桶算法控制请求频率
- 避免触发B站API的速率限制
python复制from ratelimit import limits, sleep_and_retry
# 限制每分钟30次调用
@sleep_and_retry
@limits(calls=30, period=60)
async def call_bilibili_api():
# API调用代码
- 错误处理增强:
- 增加重试机制
- 完善错误日志记录
5.3 内容质量提升
-
文本后处理:
- 增加标点修正
- 处理口语化表达
- 关键信息提取
-
提纲生成算法:
- 基于TF-IDF的关键句提取
- 层次化主题划分
- 重要性排序
python复制from sklearn.feature_extraction.text import TfidfVectorizer
def generate_outline(text, n_sentences=5):
sentences = text.split('。')
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(sentences)
scores = X.sum(axis=1)
top_sentences = [sentences[i] for i in scores.argsort(axis=0)[-n_sentences:]]
return top_sentences
6. 常见问题与解决方案
6.1 认证相关问题
问题1:获取SESSDATA等认证信息失败
解决方案:
- 确保已登录B站账号
- 检查开发者工具中Cookie是否可见
- 尝试清除Cookie后重新登录
问题2:API返回"未登录"错误
解决方案:
- 检查认证信息是否过期(通常有效期为1个月)
- 确认环境变量设置正确
- 检查是否有特殊字符需要转义
6.2 内容获取问题
问题1:无法获取视频字幕
排查步骤:
- 确认视频是否有AI生成字幕
- 检查视频时长是否超过限制
- 验证音频URL获取逻辑
问题2:语音识别准确率低
优化建议:
- 优先选择音质较好的音频流
- 增加语音识别后的文本后处理
- 考虑使用其他语音识别API作为备选
6.3 性能问题
问题1:处理速度慢
优化方案:
- 实现异步批量处理
- 增加本地缓存
- 优化网络请求
问题2:高并发时服务不稳定
解决方案:
- 增加请求队列管理
- 实现负载均衡
- 考虑分布式部署
7. 扩展与进阶应用
7.1 多平台扩展
当前实现针对B站平台,可以扩展支持:
- YouTube视频处理
- 微信公众号文章
- 知乎专栏
只需实现对应的内容获取接口,处理模块可复用。
7.2 高级内容分析
- 情感分析:识别内容情感倾向
- 关键实体提取:人物、地点、事件等
- 知识图谱构建:内容关联分析
python复制import jieba.analyse
def extract_keywords(text, topK=10):
return jieba.analyse.extract_tags(text, topK=topK)
7.3 个性化推荐
基于用户历史阅读记录,实现:
- 内容相似度推荐
- 兴趣标签匹配
- 热门趋势分析
8. 开发心得与经验分享
在实际开发过程中,有几个关键点值得特别注意:
-
API限制处理:B站API有严格的调用频率限制,必须实现合理的请求间隔控制。我的经验是维持在每分钟20-30次请求比较安全。
-
音频流选择:不同视频提供的音频流质量差异很大。通过实践发现,通常
mcdn.bilivideo.cn域名的音频流质量较好,识别准确率更高。 -
错误恢复机制:网络请求难免会失败,必须实现完善的错误处理和重试机制。我采用了指数退避算法来处理临时性失败。
-
内容结构化:直接从API获取的字幕或语音识别结果往往不够结构化。我开发了一套基于规则和机器学习相结合的内容清洗流程,显著提升了输出质量。
-
性能优化:异步IO在这个项目中至关重要。通过全面使用async/await,系统吞吐量提升了3-5倍。
