feat: 支持嵌套格式元数据(kb-bilibili-metadata 输出)
This commit is contained in:
@@ -8,41 +8,44 @@
|
|||||||
- Template-based output
|
- Template-based output
|
||||||
- Quality scoring
|
- Quality scoring
|
||||||
- Automatic tagging
|
- Automatic tagging
|
||||||
|
- **多格式元数据支持**: 支持扁平结构 `{"title":"xxx"}` 和嵌套结构 `{"data":{"metadata":{...}}}`
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Analyze content
|
# 分析内容
|
||||||
python deep_analyzer.py --metadata meta.json --content content.json --output analysis.md
|
python deep_analyzer.py --metadata meta.json --content content.json --output analysis.md
|
||||||
|
|
||||||
# Specify type
|
# 指定类型
|
||||||
python deep_analyzer.py --metadata meta.json --content content.json --type tutorial --output tutorial.md
|
python deep_analyzer.py --metadata meta.json --content content.json --type tutorial --output tutorial.md
|
||||||
|
|
||||||
|
# 指定 AI 提供商
|
||||||
|
python deep_analyzer.py -m meta.json -c content.json -o out.md --provider zhipu --model glm-4
|
||||||
```
|
```
|
||||||
|
|
||||||
## Output
|
## Metadata Format
|
||||||
|
|
||||||
```markdown
|
支持两种元数据格式:
|
||||||
---
|
|
||||||
title: "分析标题"
|
|
||||||
source: "bilibili"
|
|
||||||
quality_score: 95
|
|
||||||
tags:
|
|
||||||
- python
|
|
||||||
- tutorial
|
|
||||||
---
|
|
||||||
|
|
||||||
## 一句话总结
|
```json
|
||||||
|
// 格式1: 扁平结构
|
||||||
|
{
|
||||||
|
"title": "视频标题",
|
||||||
|
"author": "作者名",
|
||||||
|
"duration": 619,
|
||||||
|
"bvid": "BVxxx"
|
||||||
|
}
|
||||||
|
|
||||||
内容摘要...
|
// 格式2: 嵌套结构(kb-bilibili-metadata 输出)
|
||||||
|
{
|
||||||
## 核心要点
|
"data": {
|
||||||
|
"metadata": {
|
||||||
1. 要点1
|
"title": "视频标题",
|
||||||
2. 要点2
|
"author": "作者名",
|
||||||
|
"duration": "10:19"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
会自动转换为扁平格式进行分析。
|
||||||
|
|
||||||
```bash
|
|
||||||
cp -r kb-deep-analyzer/ ~/skills/
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -751,6 +751,70 @@ def load_json(file_path: str) -> Dict:
|
|||||||
return json.load(f)
|
return json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_metadata(metadata: Dict) -> Dict:
|
||||||
|
"""
|
||||||
|
标准化元数据格式,支持嵌套和平面两种结构
|
||||||
|
|
||||||
|
支持以下输入格式:
|
||||||
|
1. 扁平结构: {"title": "xxx", "author": "yyy", "duration": 619}
|
||||||
|
2. 嵌套结构: {"data": {"metadata": {"title": "xxx", "author": "yyy", "duration": "10:19"}}}
|
||||||
|
|
||||||
|
输出: 扁平结构,duration 转换为秒数
|
||||||
|
"""
|
||||||
|
if not metadata:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
# 如果已经包含 title 字段,认为是扁平结构
|
||||||
|
if 'title' in metadata:
|
||||||
|
# 处理 duration 格式(可能是 "10:19" 字符串或数字)
|
||||||
|
duration = metadata.get('duration', 0)
|
||||||
|
if isinstance(duration, str) and ':' in duration:
|
||||||
|
parts = duration.split(':')
|
||||||
|
try:
|
||||||
|
seconds = int(parts[0]) * 60 + int(parts[1])
|
||||||
|
metadata['duration'] = seconds
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
pass
|
||||||
|
return metadata
|
||||||
|
|
||||||
|
# 如果是嵌套结构,提取 data.metadata
|
||||||
|
data = metadata.get('data', {})
|
||||||
|
meta = data.get('metadata', {})
|
||||||
|
|
||||||
|
# 提取扁平化字段
|
||||||
|
normalized = {
|
||||||
|
'title': meta.get('title', metadata.get('title', '未知')),
|
||||||
|
'author': meta.get('author', metadata.get('author', '')),
|
||||||
|
'bvid': meta.get('bvid', metadata.get('bvid', '')),
|
||||||
|
'aid': meta.get('aid', metadata.get('aid', 0)),
|
||||||
|
'pubtime': meta.get('pubtime', metadata.get('pubtime', '')),
|
||||||
|
'platform': meta.get('platform', 'unknown'),
|
||||||
|
'url': meta.get('url', ''),
|
||||||
|
}
|
||||||
|
|
||||||
|
# 处理 duration
|
||||||
|
duration = meta.get('duration', 0)
|
||||||
|
if isinstance(duration, str):
|
||||||
|
if ':' in duration:
|
||||||
|
# "10:19" 格式
|
||||||
|
parts = duration.split(':')
|
||||||
|
try:
|
||||||
|
normalized['duration'] = int(parts[0]) * 60 + int(parts[1])
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
normalized['duration'] = 0
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
normalized['duration'] = int(duration)
|
||||||
|
except ValueError:
|
||||||
|
normalized['duration'] = 0
|
||||||
|
elif isinstance(duration, (int, float)):
|
||||||
|
normalized['duration'] = int(duration)
|
||||||
|
else:
|
||||||
|
normalized['duration'] = 0
|
||||||
|
|
||||||
|
return normalized
|
||||||
|
|
||||||
|
|
||||||
def format_duration(seconds: int) -> str:
|
def format_duration(seconds: int) -> str:
|
||||||
"""格式化时长"""
|
"""格式化时长"""
|
||||||
h = seconds // 3600
|
h = seconds // 3600
|
||||||
@@ -827,7 +891,8 @@ def main():
|
|||||||
|
|
||||||
# 加载数据
|
# 加载数据
|
||||||
print(f"[Main] 加载元数据: {args.metadata}")
|
print(f"[Main] 加载元数据: {args.metadata}")
|
||||||
metadata = load_json(args.metadata)
|
raw_metadata = load_json(args.metadata)
|
||||||
|
metadata = normalize_metadata(raw_metadata)
|
||||||
|
|
||||||
print(f"[Main] 加载内容: {args.content}")
|
print(f"[Main] 加载内容: {args.content}")
|
||||||
content = load_json(args.content)
|
content = load_json(args.content)
|
||||||
|
|||||||
Reference in New Issue
Block a user