92 lines
2.8 KiB
Python
92 lines
2.8 KiB
Python
"""Obsidian KB - 知乎源"""
|
|
|
|
import re
|
|
from typing import Optional
|
|
from .base import BaseSource
|
|
from ..models import Content, ContentType
|
|
|
|
try:
|
|
from .zhihu_drission_extractor import ZhihuDrissionExtractor
|
|
except ImportError:
|
|
# DrissionPage 未安装
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.warning(f"DrissionPage 未安装,无法提取知乎内容")
|
|
|
|
|
|
class ZhihuSource(BaseSource):
|
|
"""知乎文章/回答源"""
|
|
|
|
name = "zhihu"
|
|
|
|
URL_PATTERNS = [
|
|
r'zhihu\.com/question/\d+/answer/(\d+)',
|
|
r'zhuanlan\.zhihu\.com/p/(\d+)',
|
|
r'zhihu\.com/question/(\d+)',
|
|
]
|
|
|
|
def can_handle(self, url: str) -> bool:
|
|
"""检查是否为知乎链接"""
|
|
return 'zhihu.com' in url or 'zhuanlan.zhihu.com' in url
|
|
|
|
def extract_id(self, url: str) -> Optional[str]:
|
|
"""提取内容ID"""
|
|
for pattern in self.URL_PATTERNS:
|
|
match = re.search(pattern, url)
|
|
if match:
|
|
return match.group(1)
|
|
return None
|
|
|
|
def fetch(self, url: str) -> Optional[Content]:
|
|
"""获取内容元数据"""
|
|
content_id = self.extract_id(url)
|
|
if not content_id:
|
|
return None
|
|
|
|
# TODO: 使用知乎API或爬虫获取完整信息
|
|
content_type = ContentType.ARTICLE
|
|
if 'zhuanlan' in url:
|
|
content_type = ContentType.ARTICLE
|
|
|
|
return Content(
|
|
source=self.name,
|
|
source_id=content_id,
|
|
url=url,
|
|
title='',
|
|
author='',
|
|
content_type=content_type
|
|
)
|
|
|
|
def get_transcript(self, content: Content) -> Optional[str]:
|
|
"""获取文章内容"""
|
|
try:
|
|
# 使用 DrissionPage 提取器
|
|
extractor = ZhihuDrissionExtractor(
|
|
headless=self.config.get('headless', True),
|
|
timeout=self.config.get('timeout', 30),
|
|
config=self.config
|
|
)
|
|
|
|
data = extractor.extract(content.url)
|
|
|
|
if data and data.get('content_markdown'):
|
|
# 更新元数据
|
|
if data.get('title'):
|
|
content.title = data['title']
|
|
if data.get('author'):
|
|
content.author = data['author']
|
|
|
|
# 返回 Markdown 内容
|
|
return data['content_markdown']
|
|
|
|
except ImportError as e:
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.error(f"DrissionPage 导入失败: {e}")
|
|
except Exception as e:
|
|
import logging
|
|
logger = logging.getLogger(__name__)
|
|
logger.error(f"DrissionPage 提取失败: {e}")
|
|
|
|
return None
|