Skip to main content
Glama

Zhihu MCP Server

by chemany
zhihu_http_api_server.py15.9 kB
# -*- coding: utf-8 -*- """ 知乎发布HTTP API服务器 采用和小红书、头条相同的简单实现方式 """ import sys import os import time # 强制设置UTF-8编码 if hasattr(sys.stdout, 'reconfigure'): sys.stdout.reconfigure(encoding='utf-8') if hasattr(sys.stderr, 'reconfigure'): sys.stderr.reconfigure(encoding='utf-8') os.environ['PYTHONIOENCODING'] = 'utf-8' from fastapi import FastAPI from pydantic import BaseModel import uvicorn from typing import List, Optional from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.common.exceptions import TimeoutException # 导入知乎发布功能 from zhihu_mcp_server.auth import ZhihuAuth from zhihu_mcp_server.publisher import ZhihuPublisher app = FastAPI(title="知乎发布API", version="1.0.0") # 全局变量存储服务实例 auth_manager = None publisher = None def initialize_services(): """初始化服务实例""" global auth_manager, publisher try: auth_manager = ZhihuAuth() publisher = ZhihuPublisher(auth_manager) print("知乎服务实例初始化成功") # 尝试检查并预热登录环境 try: if auth_manager.check_login_status(): print("检测到已登录状态,开始预热发布环境...") driver = auth_manager.driver # 预热发布环境 - 访问写文章页面并停留在此页面 print("正在访问知乎写文章页面...") driver.get("https://zhuanlan.zhihu.com/write") # 等待编辑器加载 try: WebDriverWait(driver, 15).until( lambda driver: driver.execute_script("return document.readyState") == "complete" ) time.sleep(5) # 确保页面完全加载 # 检查是否成功加载 if "write" in driver.current_url: print("成功进入知乎文章编辑页面,发布环境预热完成") else: print(f"预热发布环境可能不完整,当前URL: {driver.current_url}") except TimeoutException: print("编辑器加载超时,预热可能不完整") else: print("初始化后未检测到登录状态,需要先登录") except Exception as e: print(f"预热发布环境失败: {e}") return True except Exception as e: print(f"知乎服务实例初始化失败: {e}") return False class CreateAnswerRequest(BaseModel): """创建回答请求模型""" question_id: str content: str images: Optional[List[str]] = None is_anonymous: bool = False class CreateArticleRequest(BaseModel): """创建文章请求模型""" title: str content: str images: Optional[List[str]] = None tags: Optional[List[str]] = None column_id: Optional[str] = None cover_image: Optional[str] = None publish_time: Optional[str] = None class CreateColumnRequest(BaseModel): """创建专栏请求模型""" title: str description: str cover_image: Optional[str] = None @app.post("/zhihu-mcp-server/create_answer") async def create_answer(request: CreateAnswerRequest): """创建知乎回答""" try: print(f"收到回答发布请求:") print(f" 问题ID: {request.question_id}") print(f" 内容长度: {len(request.content)}") print(f" 图片数量: {len(request.images) if request.images else 0}") print(f" 匿名回答: {request.is_anonymous}") # 检查服务是否初始化 if not publisher or not auth_manager: return {"status": "error", "message": "服务未初始化"} # 检查登录状态 if not auth_manager.check_login_status(): return {"status": "error", "message": "请先登录"} # 执行发布 print("开始执行回答发布...") result = publisher.create_answer( question_id=request.question_id, content=request.content, images=request.images, is_anonymous=request.is_anonymous ) print(f"回答发布结果: {result}") if result.get("success"): return {"status": "success", "message": result.get("message", "发布成功"), "data": result} else: return {"status": "error", "message": result.get("message", "发布失败"), "data": result} except Exception as e: import traceback error_msg = str(e) error_trace = traceback.format_exc() print(f"回答发布失败: {error_msg}") print(f"错误堆栈: {error_trace}") return {"status": "error", "message": error_msg, "trace": error_trace} @app.post("/zhihu-mcp-server/create_article") async def create_article(request: CreateArticleRequest): """创建知乎文章""" try: print(f"收到文章发布请求:") print(f" 标题: {request.title}") print(f" 内容长度: {len(request.content)}") print(f" 图片数量: {len(request.images) if request.images else 0}") print(f" 标签: {request.tags}") # 检查服务是否初始化 if not publisher or not auth_manager: return {"status": "error", "message": "服务未初始化"} # 检查登录状态 if not auth_manager.check_login_status(): return {"status": "error", "message": "请先登录"} # 执行发布 print("开始执行文章发布...") result = publisher.create_article( title=request.title, content=request.content, images=request.images, tags=request.tags, column_id=request.column_id, cover_image=request.cover_image, publish_time=request.publish_time ) print(f"文章发布结果: {result}") if result.get("success"): return {"status": "success", "message": result.get("message", "发布成功"), "data": result} else: return {"status": "error", "message": result.get("message", "发布失败"), "data": result} except Exception as e: import traceback error_msg = str(e) error_trace = traceback.format_exc() print(f"文章发布失败: {error_msg}") print(f"错误堆栈: {error_trace}") return {"status": "error", "message": error_msg, "trace": error_trace} @app.post("/zhihu-mcp-server/create_column") async def create_column(request: CreateColumnRequest): """创建知乎专栏""" try: print(f"收到专栏创建请求:") print(f" 标题: {request.title}") print(f" 描述: {request.description}") # 检查服务是否初始化 if not publisher or not auth_manager: return {"status": "error", "message": "服务未初始化"} # 检查登录状态 if not auth_manager.check_login_status(): return {"status": "error", "message": "请先登录"} # 执行创建 print("开始执行专栏创建...") result = publisher.create_column( title=request.title, description=request.description, cover_image=request.cover_image ) print(f"专栏创建结果: {result}") if result.get("success"): return {"status": "success", "message": result.get("message", "创建成功"), "data": result} else: return {"status": "error", "message": result.get("message", "创建失败"), "data": result} except Exception as e: import traceback error_msg = str(e) error_trace = traceback.format_exc() print(f"专栏创建失败: {error_msg}") print(f"错误堆栈: {error_trace}") return {"status": "error", "message": error_msg, "trace": error_trace} @app.get("/zhihu-mcp-server/health") async def health_check(): """健康检查接口""" try: # 检查服务状态 service_status = "initialized" if (publisher and auth_manager) else "not_initialized" # 安全地检查登录状态,如果失败不中断整个健康检查 login_status = False try: if auth_manager: login_status = auth_manager.check_login_status() except Exception as login_e: print(f"健康检查中登录状态检测失败: {login_e}") return { "status": "ok", "service_status": service_status, "login_status": login_status, "message": "知乎发布服务运行正常" } except Exception as e: return { "status": "error", "message": f"健康检查失败: {str(e)}" } @app.get("/zhihu-mcp-server/reinitialize") async def reinitialize_services(): """重新初始化服务实例 当登录状态检测失败或浏览器会话失效时, 可以通过这个接口重新初始化服务实例, 而不必重启整个API服务器 """ global auth_manager, publisher try: print("正在重新初始化服务实例...") # 关闭现有实例 if auth_manager: try: auth_manager.close() print("现有认证管理器已关闭") except Exception as e: print(f"关闭认证管理器时出错: {e}") # 重新创建实例 result = initialize_services() # 检查初始化结果 if result: # 尝试立即检查登录状态 login_status = False try: if auth_manager: login_status = auth_manager.check_login_status() print(f"服务重新初始化后登录状态: {'已登录' if login_status else '未登录'}") # 如果登录成功,执行预热操作 if login_status: print("登录成功,开始执行发布环境预热...") try: # 预热发布环境 - 访问写文章页面并停留在此页面 driver = auth_manager.driver print("正在访问写文章页面预热发布环境...") driver.get("https://zhuanlan.zhihu.com/write") # 等待编辑器加载 try: WebDriverWait(driver, 15).until( lambda driver: driver.execute_script("return document.readyState") == "complete" ) time.sleep(5) # 确保页面完全加载 # 检查是否成功加载 if "write" in driver.current_url: print("成功进入知乎文章编辑页面,发布环境预热完成") else: print(f"预热发布环境可能不完整,当前URL: {driver.current_url}") except TimeoutException: print("编辑器加载超时,预热可能不完整") except Exception as warm_e: print(f"预热发布环境失败: {warm_e}") except Exception as login_e: print(f"重新初始化后检查登录状态失败: {login_e}") return { "status": "success", "message": "服务实例重新初始化成功", "login_status": login_status } else: return { "status": "error", "message": "服务实例重新初始化失败" } except Exception as e: import traceback error_trace = traceback.format_exc() print(f"重新初始化服务时发生错误: {e}") print(f"错误堆栈: {error_trace}") return { "status": "error", "message": f"重新初始化服务时发生错误: {str(e)}" } @app.get("/zhihu-mcp-server/warmup") async def warmup_publishing_environment(): """预热发布环境 在有些情况下,浏览器会话可能已经正常,但发布环境需要预热。 此接口访问文章编辑页面,确保后续发布操作可以正常进行。 """ try: # 检查服务状态 if not publisher or not auth_manager: return {"status": "error", "message": "服务未初始化"} # 检查登录状态 login_status = False try: if auth_manager: login_status = auth_manager.check_login_status() except Exception as login_e: return {"status": "error", "message": f"检查登录状态失败: {str(login_e)}"} if not login_status: return {"status": "error", "message": "未登录,无法预热发布环境"} # 执行预热 try: driver = auth_manager.driver # 直接访问写文章页面 print("正在访问知乎写文章页面...") driver.get("https://zhuanlan.zhihu.com/write") # 等待编辑器加载 try: WebDriverWait(driver, 15).until( lambda driver: driver.execute_script("return document.readyState") == "complete" ) time.sleep(5) # 确保页面完全加载 except TimeoutException: return {"status": "error", "message": "编辑器加载超时"} # 检查是否成功加载 write_page_loaded = "write" in driver.current_url if write_page_loaded: print("成功进入知乎文章编辑页面") return { "status": "success", "message": "发布环境预热完成,已进入写文章页面", } else: print(f"可能未正确加载编辑页面,当前URL: {driver.current_url}") return { "status": "warning", "message": f"写文章页面可能未正确加载,当前URL: {driver.current_url}" } except Exception as e: import traceback error_trace = traceback.format_exc() print(f"预热发布环境失败: {e}") print(f"错误堆栈: {error_trace}") return { "status": "error", "message": f"预热发布环境失败: {str(e)}", "trace": error_trace } except Exception as e: return {"status": "error", "message": f"预热过程异常: {str(e)}"} if __name__ == "__main__": print("启动知乎发布HTTP API服务器...") # 初始化服务 if initialize_services(): print("服务初始化成功,启动HTTP API服务器...") uvicorn.run(app, host="0.0.0.0", port=8005) else: print("服务初始化失败,无法启动服务器")

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chemany/zhihu_mcp_server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server