"""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