#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ WordPress 发布系统 - 文字 + 图片发布脚本 处理从飞书等渠道发送的文字和图片,自动发布到 WordPress """ import os import sys import json import argparse import base64 import hashlib # 添加项目根目录到 Python 路径 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, BASE_DIR) from modules.wp_logger import get_publish_logger, get_debug_logger from modules.wp_image_handler import create_image_handler from modules.wp_formatter import create_formatter from modules.wp_api import create_wp_api from modules.wp_category import create_category_matcher # 配置文件路径 CONFIG_FILE = os.path.join(BASE_DIR, 'config.py') def load_config(): """加载配置文件""" config = { 'wp_url': 'https://www.nanlou.net', 'wp_user': 'shaowu', 'wp_password': 'zjzz gHYm 8Q3l KbZk y4CF 2DQi', 'default_category': 7, 'auto_match_category': True, 'optimize_images': True, 'image_max_width': 1200, 'image_quality': 85, 'post_status': 'publish' } if os.path.exists(CONFIG_FILE): try: with open(CONFIG_FILE, 'r', encoding='utf-8') as f: exec(f.read(), config) except Exception as e: print(f"加载配置文件失败:{str(e)},使用默认配置") return config def publish_text_with_images(text, images=None, instruction=None, status=None, category_id=None, tags=None, title=None): """ 发布文字 + 图片到 WordPress Args: text: 文字内容 images: 图片列表,每个图片包含 data (base64 或文件路径), filename instruction: 指令文本(可选) status: 发布状态(可选) category_id: 指定分类 ID(可选) tags: 标签列表(可选) title: 文章标题(可选,默认从内容提取) Returns: dict: 发布结果 """ # 初始化日志 pl = get_publish_logger() dl = get_debug_logger() # 加载配置 config = load_config() # 初始化各模块 wp_api = create_wp_api(config['wp_url'], config['wp_user'], config['wp_password']) image_handler = create_image_handler(config['wp_url'], config['wp_user'], config['wp_password']) formatter = create_formatter() category_matcher = create_category_matcher(wp_api) # 开始发布 pl.start_publish('文字 + 图片') try: # ========== 步骤 1:提取标题 ========== if not title: title = formatter.extract_title_from_content(text) pl.info(f"📝 文章标题:{title}") dl.log_step("提取标题", title) # ========== 步骤 2:上传图片 ========== uploaded_images = [] if images: dl.log_step("上传图片", f"共 {len(images)} 张图片") for i, img in enumerate(images): try: # 处理 base64 图片 if isinstance(img, str) and os.path.exists(img): # 文件路径 img_path = img elif isinstance(img, dict) and 'data' in img: # 字典格式(包含 base64 数据) img_data = img['data'] if isinstance(img_data, str): # base64 编码 img_data = base64.b64decode(img_data) filename = img.get('filename', f'image_{i+1}.jpg') img_hash = hashlib.md5(img_data).hexdigest()[:8] ext = os.path.splitext(filename)[1] or '.jpg' filename = f"image_{i+1}_{img_hash}{ext}" # 保存到临时文件 temp_dir = os.path.join(BASE_DIR, 'temp') os.makedirs(temp_dir, exist_ok=True) img_path = os.path.join(temp_dir, filename) with open(img_path, 'wb') as f: f.write(img_data) else: continue # 上传图片 result = image_handler.upload_image( img_path, title=f"图片 {i+1}", alt_text=f"文章配图 {i+1}" ) uploaded_images.append(result) # 清理临时文件 if 'img_path' in locals() and os.path.exists(img_path): os.remove(img_path) except Exception as e: pl.error(f"图片 {i+1} 上传失败:{str(e)}") dl.error(f"图片上传失败:{str(e)}", exc_info=True) pl.info(f"📤 图片上传完成 - 成功 {len(uploaded_images)} 张") # ========== 步骤 3:匹配分类 ========== if category_id: final_category_id = category_id else: final_category_id = category_matcher.match( instruction=instruction, title=title, content=text, auto_match=config.get('auto_match_category', True) ) # ========== 步骤 4:格式化 HTML ========== dl.log_step("格式化 HTML 内容") # 先格式化文字内容 content_html = formatter.format_text_content(text) # 插入图片 if uploaded_images: # 将图片插入到内容中(每段之间) paragraphs = content_html.split('
') new_html = [] img_index = 0 for para in paragraphs: para = para.strip() if not para: continue new_html.append(para + '') # 在段落间插入图片 if img_index < len(uploaded_images): img = uploaded_images[img_index] if 'url' in img: img_html = f'