This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
kb-skills/kb-zhihu-metadata/zhihu_metadata.py
T
starmen1265 d2c262973e feat: 添加知乎问答支持
- zhihu_extractor.py:
  - 添加 URL_PATTERNS 支持 answer 和 question
  - 添加 _extract_answer_content() 方法提取知乎回答
  - 添加 _extract_question_content() 方法提取知乎问题

- zhihu_metadata.py:
  - 添加 extract_answer() 函数
  - 添加 extract_question() 函数
  - 更新命令行参数支持 answer/question 类型
  - 更新帮助文档
2026-02-16 22:12:13 +08:00

199 lines
5.6 KiB
Python

#!/usr/bin/env python3
"""
知乎元数据获取工具
支持以下内容类型:
- zvideo: 知乎视频 (https://www.zhihu.com/zvideo/xxx)
- zhuanlan: 知乎专栏文章 (https://zhuanlan.zhihu.com/p/xxx)
- answer: 知乎回答 (https://www.zhihu.com/question/xxx/answer/yyy)
- question: 知乎问题 (https://www.zhihu.com/question/xxx)
"""
import argparse
import json
import sys
import os
from typing import Dict, Optional, Any
# 添加当前目录到 Python 路径
current_dir = os.path.dirname(os.path.abspath(__file__))
if current_dir not in sys.path:
sys.path.insert(0, current_dir)
from zhihu_extractor import ZhihuPlaywrightExtractor
def extract_zvideo(video_id: str, headless: bool = True) -> Dict[str, Any]:
"""
获取知乎视频元数据
Args:
video_id: 视频 ID (数字字符串)
headless: 是否使用无头浏览器
Returns:
视频元数据字典
"""
url = f"https://www.zhihu.com/zvideo/{video_id}"
return _extract_metadata(url, "zvideo", headless)
def extract_zhuanlan(article_id: str, headless: bool = True) -> Dict[str, Any]:
"""
获取知乎专栏文章元数据
Args:
article_id: 文章 ID (数字字符串)
headless: 是否使用无头浏览器
Returns:
文章元数据字典
"""
url = f"https://zhuanlan.zhihu.com/p/{article_id}"
return _extract_metadata(url, "zhuanlan", headless)
def extract_answer(answer_id: str, headless: bool = True) -> Dict[str, Any]:
"""
获取知乎回答元数据
Args:
answer_id: 回答 ID (数字字符串)
headless: 是否使用无头浏览器
Returns:
回答元数据字典
"""
# 回答需要构建包含问题ID的URL,但answer_id本身足以识别
# 使用一个占位符问题ID,因为提取器会从URL中提取answer_id
url = f"https://www.zhihu.com/question/0/answer/{answer_id}"
return _extract_metadata(url, "answer", headless)
def extract_question(question_id: str, headless: bool = True) -> Dict[str, Any]:
"""
获取知乎问题元数据
Args:
question_id: 问题 ID (数字字符串)
headless: 是否使用无头浏览器
Returns:
问题元数据字典
"""
url = f"https://www.zhihu.com/question/{question_id}"
return _extract_metadata(url, "question", headless)
def _extract_metadata(url: str, content_type: str, headless: bool) -> Dict[str, Any]:
"""
内部函数:提取元数据
Args:
url: 知乎 URL
content_type: 内容类型 (zvideo/zhuanlan)
headless: 是否使用无头浏览器
Returns:
元数据字典
"""
extractor = ZhihuPlaywrightExtractor(headless=headless)
result = extractor.extract(url)
if result:
# 标准化输出格式
metadata = {
"type": content_type,
"id": result.get("content_id", ""),
"url": result.get("url", url),
"title": result.get("title", ""),
"author": result.get("author", ""),
"publish_time": result.get("publish_time", ""),
"vote_up": result.get("vote_up", 0),
"content_markdown": result.get("content_markdown", ""),
"raw_html": result.get("content", ""),
}
return metadata
else:
return {
"type": content_type,
"error": "Failed to extract content",
"url": url
}
def main():
"""命令行入口"""
parser = argparse.ArgumentParser(
description="知乎元数据获取工具",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
支持的类型:
zvideo - 知乎视频 (https://www.zhihu.com/zvideo/123456)
zhuanlan - 知乎专栏文章 (https://zhuanlan.zhihu.com/p/123456)
answer - 知乎回答 (https://www.zhihu.com/question/xxx/answer/yyy)
question - 知乎问题 (https://www.zhihu.com/question/xxx)
示例:
python zhihu_metadata.py --id "123456" --type zvideo
python zhihu_metadata.py --id "123456" --type zhuanlan
python zhihu_metadata.py --id "123456" --type answer
python zhihu_metadata.py --id "123456" --type question
"""
)
parser.add_argument(
"--id", "-i",
required=True,
help="知乎内容 ID (视频ID/文章ID/回答ID/问题ID)"
)
parser.add_argument(
"--type", "-t",
required=True,
choices=["zvideo", "zhuanlan", "answer", "question"],
help="内容类型: zvideo=视频, zhuanlan=专栏文章, answer=回答, question=问题"
)
parser.add_argument(
"--output", "-o",
default=None,
help="输出文件路径 (默认: stdout)"
)
parser.add_argument(
"--headless",
action="store_true",
default=True,
help="使用无头浏览器模式 (默认: True)"
)
args = parser.parse_args()
# 提取元数据
if args.type == "zvideo":
result = extract_zvideo(args.id, headless=args.headless)
elif args.type == "zhuanlan":
result = extract_zhuanlan(args.id, headless=args.headless)
elif args.type == "answer":
result = extract_answer(args.id, headless=args.headless)
elif args.type == "question":
result = extract_question(args.id, headless=args.headless)
else:
print(f"不支持的类型: {args.type}")
sys.exit(1)
# 输出结果
json_output = json.dumps(result, ensure_ascii=False, indent=2)
if args.output:
with open(args.output, 'w', encoding='utf-8') as f:
f.write(json_output)
print(f"结果已保存到: {args.output}")
else:
print(json_output)
if __name__ == "__main__":
main()