#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ WordPress 发布系统 - 分类匹配模块 根据指令或内容自动匹配 WordPress 分类 """ import re from modules.wp_logger import get_publish_logger, get_debug_logger # 默认分类配置 DEFAULT_CATEGORY_ID = 7 # 随笔 DEFAULT_CATEGORY_NAME = '随笔' # 分类关键词映射(用于 AI 自动匹配) CATEGORY_KEYWORDS = { 12: ['ai 科普', '人工智能科普', 'ai 入门', '科普'], # Ai 科普 11: ['ai 资讯', '人工智能新闻', 'ai 新闻', '资讯', '行业动态'], # Ai 资讯 16: ['geo', '生成式引擎优化', '搜索优化'], # GEO 9: ['人工智能', 'ai', '机器学习', '深度学习', '神经网络', '大模型'], # 人工智能 5: ['技术', '教程', '开发', '编程', '代码', '技术资料'], # 技术资料 10: ['好物', '推荐', '分享', '产品', '测评'], # 好物分享 4: ['文章', '转载', '译文', '翻译'], # 文章分享 8: ['杂记', 'misc', '其他'], # 杂记 7: ['随笔', '日记', '心情', '感想'], # 随笔 1: ['关于', '网站', '联系', '声明'], # 关于我们 } class CategoryMatcher: """分类匹配器""" def __init__(self, wp_api): """ 初始化分类匹配器 Args: wp_api: WordPress API 客户端实例 """ self.wp_api = wp_api self.categories_cache = [] self.default_category_id = DEFAULT_CATEGORY_ID self.pl = get_publish_logger() self.dl = get_debug_logger() def load_categories(self): """加载分类列表""" self.categories_cache = self.wp_api.get_categories() self.dl.debug(f"已加载 {len(self.categories_cache)} 个分类") return self.categories_cache def match_by_slug(self, slug): """ 根据 slug 匹配分类 Args: slug: 分类 slug Returns: int: 分类 ID,未找到返回默认分类 """ if not slug: return self.default_category_id slug = slug.lower().strip() for category in self.categories_cache: if category.get('slug', '').lower() == slug: self.dl.debug(f"通过 slug 匹配到分类:{category['name']} (ID: {category['id']})") return category['id'] self.dl.warning(f"未找到 slug 为 '{slug}' 的分类,使用默认分类") return self.default_category_id def match_by_name(self, name): """ 根据名称匹配分类 Args: name: 分类名称 Returns: int: 分类 ID,未找到返回默认分类 """ if not name: return self.default_category_id name = name.strip() for category in self.categories_cache: if category.get('name', '').strip() == name: self.dl.debug(f"通过名称匹配到分类:{category['name']} (ID: {category['id']})") return category['id'] self.dl.warning(f"未找到名称为 '{name}' 的分类,使用默认分类") return self.default_category_id def match_by_instruction(self, instruction): """ 根据指令文本匹配分类 Args: instruction: 指令文本(如 "#分类 技术" 或 "分类:ai") Returns: int: 分类 ID """ if not instruction: return self.default_category_id instruction = instruction.strip().lower() # 匹配多种指令格式 patterns = [ r'#分类\s*([^\s#]+)', # #分类 技术 r'#category\s*([^\s#]+)', # #category tech r'分类 [::]\s*([^\s\n]+)', # 分类:技术 r'分类 [::]\s*([^\s\n]+)', # 分类:tech r'发布到\s*([^\s\n]+)', # 发布到 技术 ] for pattern in patterns: match = re.search(pattern, instruction, re.IGNORECASE) if match: category_value = match.group(1).strip() self.dl.debug(f"从指令中提取分类:{category_value}") # 尝试匹配 slug category_id = self.match_by_slug(category_value) if category_id != self.default_category_id: return category_id # 尝试匹配名称 category_id = self.match_by_name(category_value) if category_id != self.default_category_id: return category_id self.dl.warning("指令中未找到有效分类,使用默认分类") return self.default_category_id def match_by_content(self, title, content): """ 根据内容自动匹配分类(AI 匹配) Args: title: 文章标题 content: 文章内容 Returns: int: 分类 ID """ if not title and not content: return self.default_category_id # 合并标题和内容用于分析 text = f"{title} {content}".lower() # 统计每个分类的关键词匹配分数 scores = {} for cat_id, keywords in CATEGORY_KEYWORDS.items(): score = 0 for keyword in keywords: if keyword.lower() in text: score += 1 if score > 0: scores[cat_id] = score if scores: # 返回得分最高的分类 best_cat_id = max(scores, key=scores.get) best_score = scores[best_cat_id] # 获取分类名称 cat_name = "未知" for category in self.categories_cache: if category['id'] == best_cat_id: cat_name = category['name'] break self.dl.debug(f"AI 匹配分类:{cat_name} (ID: {best_cat_id}, 得分:{best_score})") return best_cat_id self.dl.debug("内容未匹配到关键词,使用默认分类") return self.default_category_id def match(self, instruction=None, title=None, content=None, auto_match=True): """ 综合匹配分类 Args: instruction: 指令文本(优先级最高) title: 文章标题 content: 文章内容 auto_match: 是否启用自动匹配 Returns: int: 分类 ID """ # 确保分类列表已加载 if not self.categories_cache: self.load_categories() # 优先级 1:指令匹配 if instruction: category_id = self.match_by_instruction(instruction) if category_id != self.default_category_id: self.pl.info(f"📂 分类:根据指令匹配到分类 ID {category_id}") return category_id # 优先级 2:自动匹配(如果启用) if auto_match and (title or content): category_id = self.match_by_content(title or '', content or '') if category_id != self.default_category_id: self.pl.info(f"📂 分类:根据内容自动匹配到分类 ID {category_id}") return category_id # 默认分类 self.pl.info(f"📂 分类:使用默认分类 ID {self.default_category_id}") return self.default_category_id def get_category_list(self): """ 获取分类列表(用于显示) Returns: list: 分类信息列表 """ if not self.categories_cache: self.load_categories() return [ { 'id': cat['id'], 'name': cat['name'], 'slug': cat['slug'], 'keywords': CATEGORY_KEYWORDS.get(cat['id'], []) } for cat in self.categories_cache ] def create_category_matcher(wp_api): """创建分类匹配器实例""" return CategoryMatcher(wp_api) if __name__ == '__main__': import sys if len(sys.argv) < 4: print("用法:python wp_category.py [instruction]") sys.exit(1) wp_url = sys.argv[1] wp_user = sys.argv[2] wp_password = sys.argv[3] instruction = sys.argv[4] if len(sys.argv) > 4 else None from modules.wp_api import create_wp_api api = create_wp_api(wp_url, wp_user, wp_password) matcher = create_category_matcher(api) # 显示所有分类 print("可用分类列表:") for cat in matcher.get_category_list(): print(f" ID: {cat['id']}, 名称:{cat['name']}, Slug: {cat['slug']}") if cat['keywords']: print(f" 关键词:{', '.join(cat['keywords'])}") # 测试匹配 if instruction: print(f"\n指令 '{instruction}' 匹配结果:") category_id = matcher.match(instruction=instruction) print(f" 匹配到分类 ID: {category_id}")