refactor: 移除bilibili_extractor插件,改用obsidian-kb
- 删除 bilibili_extractor.py 及相关文档和配置 - 删除 bilibili_venv 虚拟环境 - 删除测试脚本和生成的B站笔记 - 以后使用 skills/obsidian-kb 提供的B站提取功能
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
# B站提取器实现 - Checkpoint 3 完成报告
|
||||
|
||||
## 任务完成情况
|
||||
|
||||
✅ 所有任务已完成
|
||||
|
||||
## 实现的功能
|
||||
|
||||
### 1. 创建了 B站提取器类
|
||||
- 文件路径:`/home/admin/.openclaw/workspace/skills/obsidian-kb/src/extractors/bilibili_extractor.py`
|
||||
- 继承自 `src/extractors/base.py` 的 `Extractor` 基类
|
||||
- 实现了 `extract(source_id: str)` 方法,返回字典结构
|
||||
|
||||
### 2. 核心功能实现
|
||||
|
||||
#### 输入格式支持
|
||||
- ✅ BV号:`BV1MnFNz5EDL`
|
||||
- ✅ 完整URL:`https://www.bilibili.com/video/BV1MnFNz5EDL`
|
||||
- ✅ 短链接:`https://b23.tv/xxx`(框架已实现,需额外解析)
|
||||
|
||||
#### 返回数据结构
|
||||
```python
|
||||
{
|
||||
'metadata': {
|
||||
'title': '视频标题',
|
||||
'author': 'UP主名称',
|
||||
'bvid': 'BV号',
|
||||
'aid': 'AV号',
|
||||
'duration': '12:38',
|
||||
'pubtime': '2026-02-02 17:49:13',
|
||||
'tags': '标签列表',
|
||||
'mid': 'UP主ID',
|
||||
},
|
||||
'stats': {
|
||||
'view': 播放量,
|
||||
'like': 点赞数,
|
||||
'coin': 投币数,
|
||||
'favorite': 收藏数,
|
||||
'share': 分享数,
|
||||
'danmaku': 弹幕数,
|
||||
'reply': 评论数,
|
||||
},
|
||||
'subtitle': '字幕内容(如果有)',
|
||||
'description': '视频描述',
|
||||
}
|
||||
```
|
||||
|
||||
#### 配置支持
|
||||
- ✅ 使用配置中的 `bilibili_headless`(默认 True)
|
||||
- ✅ 使用配置中的 `bilibili_timeout`(默认 30 秒)
|
||||
|
||||
### 3. 提取策略
|
||||
|
||||
采用双策略提取方案:
|
||||
|
||||
1. **API优先策略**(推荐)
|
||||
- 直接调用 B站 API:`https://api.bilibili.com/x/web-interface/view`
|
||||
- 优点:快速、稳定、资源消耗少
|
||||
- 缺点:可能受 API 限制影响
|
||||
|
||||
2. **页面备用策略**
|
||||
- 使用 Playwright 访问完整页面
|
||||
- 支持多种提取方法:
|
||||
- JavaScript 变量提取(`window.__INITIAL_STATE__`)
|
||||
- HTML 元素提取
|
||||
- API 回退
|
||||
- 支持 stealth 模式(可配置)
|
||||
|
||||
### 4. Playwright 集成
|
||||
|
||||
- 使用 Playwright 的 `async_api` 实现异步操作
|
||||
- 支持无头模式(headless)和有头模式
|
||||
- 配置了反检测参数(User-Agent、Referer、Locale 等)
|
||||
- 可选 stealth 模式(使用 `undetected-playwright`)
|
||||
|
||||
## 测试结果
|
||||
|
||||
### 测试用例
|
||||
|
||||
使用真实视频 BV号 `BV1MnFNz5EDL` 进行测试:
|
||||
|
||||
#### 测试 1:BV号格式
|
||||
```
|
||||
输入: BV1MnFNz5EDL
|
||||
结果: ✅ 成功
|
||||
```
|
||||
|
||||
#### 测试 2:完整URL格式
|
||||
```
|
||||
输入: https://www.bilibili.com/video/BV1MnFNz5EDL
|
||||
结果: ✅ 成功
|
||||
```
|
||||
|
||||
### 提取结果示例
|
||||
|
||||
```json
|
||||
{
|
||||
"metadata": {
|
||||
"title": "【老戴】用了几天 Clawdbot,我最担心的事开始发生了",
|
||||
"author": "老戴Donald",
|
||||
"bvid": "BV1MnFNz5EDL",
|
||||
"aid": 116000406116354,
|
||||
"duration": "12:38",
|
||||
"pubtime": "2026-02-02 17:49:13",
|
||||
"tags": "",
|
||||
"mid": 3493075691243699
|
||||
},
|
||||
"stats": {
|
||||
"view": 59074,
|
||||
"like": 3292,
|
||||
"coin": 2354,
|
||||
"favorite": 1692,
|
||||
"share": 587,
|
||||
"danmaku": 482,
|
||||
"reply": 506
|
||||
},
|
||||
"subtitle": "",
|
||||
"description": "用了几天 Clawdbot——是的,它很不稳定,很不成熟,很糙。\n我关注的并不是它能干多少事,而是:\n当未来 AI 的能力和资源不可避免地走向集中,\n数据的主权,还会不会掌握在大众手里。\n如果垄断不可避免,开源可能就是最后的防线。"
|
||||
}
|
||||
```
|
||||
|
||||
## 代码关键部分
|
||||
|
||||
### 1. 类定义和初始化
|
||||
|
||||
```python
|
||||
class BilibiliExtractor(Extractor):
|
||||
"""B站视频信息提取器"""
|
||||
|
||||
def __init__(self, config=None):
|
||||
self.config = config
|
||||
self.headless = getattr(config, 'bilibili_headless', True)
|
||||
self.timeout = getattr(config, 'bilibili_timeout', 30) * 1000
|
||||
```
|
||||
|
||||
### 2. extract 方法实现
|
||||
|
||||
```python
|
||||
def extract(self, source_id: str) -> Dict[str, Any]:
|
||||
"""提取视频信息"""
|
||||
try:
|
||||
# 解析 source_id 获取 BV 号
|
||||
bvid = self._parse_source_id(source_id)
|
||||
if not bvid:
|
||||
raise ExtractionError(f"无法解析 source_id: {source_id}", source_id)
|
||||
|
||||
# 运行异步提取
|
||||
result = asyncio.run(self._extract_async(bvid))
|
||||
|
||||
if not result:
|
||||
raise ExtractionError(f"提取失败: {source_id}", source_id)
|
||||
|
||||
return result
|
||||
|
||||
except ExtractionError:
|
||||
raise
|
||||
except Exception as e:
|
||||
self._handle_error(e, source_id)
|
||||
```
|
||||
|
||||
### 3. 双策略提取
|
||||
|
||||
```python
|
||||
async def _extract_video_info(self, bvid: str) -> Dict[str, Any]:
|
||||
# 优先使用 API 方法(更快速、更稳定)
|
||||
try:
|
||||
video_info = await self._extract_from_api(bvid)
|
||||
if video_info and video_info.get('title'):
|
||||
print(f"✓ API 提取成功")
|
||||
subtitles = await self._extract_subtitles(bvid)
|
||||
return self._build_result(video_info, subtitles)
|
||||
except Exception as e:
|
||||
print(f"API 提取失败,尝试页面提取: {e}")
|
||||
|
||||
# 如果 API 失败,尝试访问页面
|
||||
# ... 页面提取逻辑
|
||||
```
|
||||
|
||||
### 4. source_id 解析
|
||||
|
||||
```python
|
||||
def _parse_source_id(self, source_id: str) -> Optional[str]:
|
||||
"""解析 source_id 获取 BV 号"""
|
||||
source_id = source_id.strip()
|
||||
|
||||
# 尝试匹配完整URL
|
||||
url_match = self.URL_PATTERN.search(source_id)
|
||||
if url_match:
|
||||
return url_match.group(1)
|
||||
|
||||
# 尝试匹配BV号
|
||||
bvid_match = self.BVID_PATTERN.search(source_id)
|
||||
if bvid_match:
|
||||
return bvid_match.group(0)
|
||||
|
||||
return None
|
||||
```
|
||||
|
||||
## 依赖安装
|
||||
|
||||
```bash
|
||||
# 创建虚拟环境
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
|
||||
# 安装依赖
|
||||
pip install playwright undetected-playwright beautifulsoup4 lxml pyyaml
|
||||
|
||||
# 安装 Playwright 浏览器
|
||||
playwright install chromium
|
||||
```
|
||||
|
||||
## 文件清单
|
||||
|
||||
1. ✅ `/home/admin/.openclaw/workspace/skills/obsidian-kb/src/extractors/bilibili_extractor.py` - B站提取器实现
|
||||
2. ✅ 测试脚本:
|
||||
- `test_playwright.py` - Playwright 基本功能测试
|
||||
- `test_bilibili_api.py` - B站 API 测试
|
||||
- `test_api_only.py` - API 提取测试
|
||||
- `simple_test2.py` - 简单提取器测试
|
||||
- `complete_test.py` - 完整测试
|
||||
|
||||
## 后续优化建议
|
||||
|
||||
1. **短链接解析**:实现 `b23.tv` 短链接解析功能
|
||||
2. **字幕提取优化**:处理需要权限的字幕
|
||||
3. **错误处理增强**:添加更多异常处理和重试机制
|
||||
4. **Stealth 模式**:如需更强的反爬虫能力,可以启用 stealth 模式
|
||||
5. **性能优化**:缓存机制、并发请求等
|
||||
|
||||
## 总结
|
||||
|
||||
Checkpoint 3 已成功完成!B站提取器已实现并测试通过,可以正常提取视频元数据、统计数据和描述信息。采用 API 优先策略,速度快且稳定;同时保留页面备用策略,确保可靠性。
|
||||
Reference in New Issue
Block a user