refactor: 统一CLI输出格式为标准JSON
This commit is contained in:
@@ -204,7 +204,6 @@ async def main():
|
||||
parser.add_argument('--type', '-t', required=True, choices=['video', 'subtitle', 'article'], help='内容类型')
|
||||
parser.add_argument('--output', '-o', default='./output', help='输出目录')
|
||||
parser.add_argument('--quality', '-q', type=int, default=32, help='视频质量: 16=360P, 32=480P, 64=720P, 80=1080P')
|
||||
parser.add_argument('--json', action='store_true', help='JSON输出')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -218,13 +217,23 @@ async def main():
|
||||
else:
|
||||
result = await downloader.extract_article(args.id.replace('cv', ''))
|
||||
|
||||
if args.json:
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
# 统一输出格式
|
||||
if result.get("success"):
|
||||
output = {
|
||||
"success": True,
|
||||
"type": args.type,
|
||||
"filename": Path(result.get('filepath', '')).name if result.get('filepath') else None,
|
||||
"filepath": str(Path(result.get('filepath', '')).resolve()) if result.get('filepath') else None,
|
||||
"message": result.get('message', '处理成功')
|
||||
}
|
||||
else:
|
||||
print(f"\n{result['message']}")
|
||||
if result.get('filepath'):
|
||||
print(f"文件: {result['filepath']}")
|
||||
output = {
|
||||
"success": False,
|
||||
"error": result.get('message', '处理失败'),
|
||||
"detail": f"ID: {args.id}, 类型: {args.type}"
|
||||
}
|
||||
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
return result
|
||||
|
||||
|
||||
@@ -233,5 +242,8 @@ if __name__ == '__main__':
|
||||
result = asyncio.run(main())
|
||||
sys.exit(0 if result.get("success") else 1)
|
||||
except KeyboardInterrupt:
|
||||
print("\n已取消")
|
||||
print(json.dumps({"success": False, "error": "用户取消"}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(json.dumps({"success": False, "error": str(e)}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
@@ -176,7 +176,10 @@ def main():
|
||||
result = extract_up(extractor, args.id, args.output)
|
||||
elif args.type == 'series':
|
||||
if not args.mid:
|
||||
print("错误: series类型需要提供 --mid 参数")
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": "series类型需要提供 --mid 参数"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
result = extract_series(extractor, args.mid, args.id, args.output)
|
||||
elif args.type == 'readlist':
|
||||
@@ -184,37 +187,33 @@ def main():
|
||||
elif args.type == 'favlist':
|
||||
result = extract_favlist(extractor, args.id, args.output)
|
||||
else:
|
||||
print(f"错误: 不支持的类型 {args.type}")
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": f"不支持的类型 {args.type}"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
# 包装为标准输出格式
|
||||
# 生成文件名
|
||||
platform = "bilibili"
|
||||
filename = f"{platform}_{args.id}.meta.json"
|
||||
filepath = args.output or filename
|
||||
|
||||
# 统一输出格式
|
||||
output = {
|
||||
"success": True,
|
||||
"data": result,
|
||||
"metadata": {
|
||||
"type": args.type,
|
||||
"id": args.id,
|
||||
"fetched_at": "2024-01-01T00:00:00"
|
||||
}
|
||||
"filename": filename,
|
||||
"filepath": str(Path(filepath).resolve()) if filepath else None,
|
||||
"message": f"{args.type}元数据提取成功"
|
||||
}
|
||||
|
||||
# 输出结果
|
||||
if not args.output:
|
||||
if args.pretty:
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
print(json.dumps(output, ensure_ascii=False))
|
||||
|
||||
if args.output:
|
||||
print(f"结果已保存到: {args.output}")
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
|
||||
except Exception as e:
|
||||
error_output = {
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": str(e),
|
||||
"error_type": type(e).__name__
|
||||
}
|
||||
print(json.dumps(error_output, ensure_ascii=False, indent=2))
|
||||
"detail": type(e).__name__
|
||||
}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
@@ -951,10 +951,27 @@ def main():
|
||||
with open(args.output, 'w', encoding='utf-8') as f:
|
||||
f.write(markdown_content)
|
||||
|
||||
print(f"[Main] 分析完成!输出: {args.output}")
|
||||
print(f"[Main] 摘要: {result.summary[:100]}...")
|
||||
print(f"[Main] 主题数: {len(result.main_topics)}")
|
||||
# 统一输出格式
|
||||
output = {
|
||||
"success": True,
|
||||
"filename": Path(args.output).name,
|
||||
"filepath": str(Path(args.output).resolve()),
|
||||
"message": "深度分析完成",
|
||||
"stats": {
|
||||
"summary_length": len(result.summary),
|
||||
"topics_count": len(result.main_topics),
|
||||
"insights_count": len(result.key_insights)
|
||||
}
|
||||
}
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except Exception as e:
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": str(e)
|
||||
}, ensure_ascii=False, indent=2))
|
||||
sys.exit(1)
|
||||
|
||||
@@ -565,30 +565,69 @@ Examples:
|
||||
|
||||
if args.url:
|
||||
# Single URL mode
|
||||
result = link_parser.parse(args.url)
|
||||
print(format_output(result, args.format))
|
||||
return 0 if result["success"] else 1
|
||||
parsed = link_parser.parse(args.url)
|
||||
|
||||
# 统一输出格式
|
||||
if parsed["success"]:
|
||||
output = {
|
||||
"success": True,
|
||||
"platform": parsed.get("platform"),
|
||||
"type": parsed.get("type"),
|
||||
"id": parsed.get("id"),
|
||||
"filename": f"{parsed.get('platform')}_{parsed.get('id')}.link.json" if parsed.get("platform") and parsed.get("id") else None,
|
||||
"message": "URL解析成功"
|
||||
}
|
||||
else:
|
||||
output = {
|
||||
"success": False,
|
||||
"error": parsed.get("error", "解析失败"),
|
||||
"detail": f"URL: {args.url}"
|
||||
}
|
||||
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
return 0 if output["success"] else 1
|
||||
|
||||
elif args.batch:
|
||||
try:
|
||||
with open(args.batch, 'r', encoding='utf-8') as f:
|
||||
urls = [line.strip() for line in f if line.strip()]
|
||||
except Exception as e:
|
||||
print(f"Error reading file: {e}", file=sys.stderr)
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": "读取文件失败",
|
||||
"detail": str(e)
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 1
|
||||
|
||||
results = []
|
||||
for url in urls:
|
||||
result = link_parser.parse(url)
|
||||
results.append(result)
|
||||
parsed = link_parser.parse(url)
|
||||
if parsed["success"]:
|
||||
results.append({
|
||||
"success": True,
|
||||
"platform": parsed.get("platform"),
|
||||
"type": parsed.get("type"),
|
||||
"id": parsed.get("id"),
|
||||
"filename": f"{parsed.get('platform')}_{parsed.get('id')}.link.json" if parsed.get("platform") and parsed.get("id") else None
|
||||
})
|
||||
else:
|
||||
results.append({
|
||||
"success": False,
|
||||
"error": parsed.get("error", "解析失败"),
|
||||
"detail": f"URL: {url}"
|
||||
})
|
||||
|
||||
if args.output:
|
||||
with open(args.output, 'w', encoding='utf-8') as f:
|
||||
json.dump(results, f, ensure_ascii=False, indent=2)
|
||||
print(f"Results written to {args.output}")
|
||||
print(json.dumps({
|
||||
"success": True,
|
||||
"message": f"结果已保存到 {args.output}",
|
||||
"total": len(results)
|
||||
}, ensure_ascii=False, indent=2))
|
||||
else:
|
||||
for result in results:
|
||||
print(format_output(result, args.format))
|
||||
print(json.dumps(result, ensure_ascii=False, indent=2))
|
||||
print("-" * 40)
|
||||
|
||||
return 0
|
||||
|
||||
@@ -304,7 +304,10 @@ def main():
|
||||
input_dir = args.input
|
||||
if args.video:
|
||||
if not os.path.exists(args.video):
|
||||
print(f"❌ 视频文件不存在: {args.video}")
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": f"视频文件不存在: {args.video}"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 1
|
||||
|
||||
# 创建临时帧目录
|
||||
@@ -312,6 +315,10 @@ def main():
|
||||
input_dir = extract_frames(args.video, frames_dir, fps=args.fps)
|
||||
|
||||
if not input_dir:
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": "截帧失败"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 1
|
||||
|
||||
# 初始化处理器
|
||||
@@ -324,19 +331,29 @@ def main():
|
||||
# 保存结果
|
||||
processor.save_results(results, args.output, merge=args.merge)
|
||||
|
||||
# 打印摘要
|
||||
# 统一输出格式
|
||||
total_texts = sum(1 for r in results if r.get("text"))
|
||||
avg_conf = sum(r.get("confidence", 0) for r in results) / len(results) if results else 0
|
||||
|
||||
print(f"\n=== 摘要 ===")
|
||||
print(f"处理帧数: {len(results)}")
|
||||
print(f"识别到文字的帧: {total_texts}")
|
||||
print(f"平均置信度: {avg_conf:.2%}")
|
||||
output = {
|
||||
"success": True,
|
||||
"filename": Path(args.output).name,
|
||||
"filepath": str(Path(args.output).resolve()),
|
||||
"message": f"OCR处理完成",
|
||||
"stats": {
|
||||
"total_frames": len(results),
|
||||
"frames_with_text": total_texts,
|
||||
"avg_confidence": round(avg_conf, 4)
|
||||
}
|
||||
}
|
||||
print(json.dumps(output, ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
else:
|
||||
print("未处理到任何结果")
|
||||
print(json.dumps({
|
||||
"success": False,
|
||||
"error": "未处理到任何结果"
|
||||
}, ensure_ascii=False, indent=2))
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user