#!/usr/bin/env python3 """ 高级图片生成器 使用ImageMagick创建专业的技术资讯图片 """ import os import subprocess import tempfile from datetime import datetime import json class AdvancedImageGenerator: """高级图片生成器""" def __init__(self): self.temp_dir = "/tmp/xiaohongshu_images" os.makedirs(self.temp_dir, exist_ok=True) def create_tech_news_image(self, title, source, content_preview=None, style="modern"): """ 创建技术资讯图片 Args: title: 文章标题 source: 文章来源 content_preview: 内容预览(可选) style: 图片风格(modern, minimal, gradient, tech) Returns: 图片文件路径 """ print(f"🎨 创建技术资讯图片 (风格: {style})...") timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") output_file = os.path.join(self.temp_dir, f"tech_news_{timestamp}.jpg") # 根据风格选择生成方法 if style == "modern": return self._create_modern_style(title, source, content_preview, output_file) elif style == "minimal": return self._create_minimal_style(title, source, output_file) elif style == "gradient": return self._create_gradient_style(title, source, output_file) elif style == "tech": return self._create_tech_style(title, source, output_file) else: return self._create_modern_style(title, source, content_preview, output_file) def _create_modern_style(self, title, source, content_preview, output_file): """现代风格图片""" try: # 基础图片 cmd = [ 'convert', '-size', '800x600', 'gradient:#1a237e-#4a148c', # 深蓝到紫色渐变 '-fill', 'white', '-stroke', 'none', output_file ] subprocess.run(cmd, check=True) # 添加标题 title_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans-Bold', '-pointsize', '36', '-fill', 'white', '-gravity', 'North', '-annotate', '+0+50', f'📰 技术资讯', output_file ] subprocess.run(title_cmd, check=True) # 添加分隔线 line_cmd = [ 'convert', output_file, '-stroke', '#4fc3f7', '-strokewidth', '3', '-draw', 'line 50,120 750,120', output_file ] subprocess.run(line_cmd, check=True) # 添加文章标题(分多行) title_lines = self._split_text(title, 30) for i, line in enumerate(title_lines[:3]): y_offset = 150 + i * 40 text_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '24', '-fill', 'white', '-gravity', 'NorthWest', '-annotate', f'+50+{y_offset}', line, output_file ] subprocess.run(text_cmd, check=True) # 添加来源和时间 info_text = f"来源: {source} | 时间: {datetime.now().strftime('%Y-%m-%d %H:%M')}" info_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '18', '-fill', '#b0bec5', '-gravity', 'SouthWest', '-annotate', '+50+50', info_text, output_file ] subprocess.run(info_cmd, check=True) # 添加自动化标识 auto_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '16', '-fill', '#4fc3f7', '-gravity', 'SouthEast', '-annotate', '+50+50', 'IT资讯自动化系统', output_file ] subprocess.run(auto_cmd, check=True) print(f"✅ 现代风格图片创建成功: {output_file}") return output_file except Exception as e: print(f"❌ 创建现代风格图片失败: {e}") return self._create_fallback_image(title, source, output_file) def _create_minimal_style(self, title, source, output_file): """极简风格图片""" try: # 纯色背景 cmd = [ 'convert', '-size', '800x600', 'xc:#f5f5f5', # 浅灰色背景 '-fill', '#333333', '-stroke', 'none', output_file ] subprocess.run(cmd, check=True) # 添加标题 title_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans-Bold', '-pointsize', '32', '-fill', '#2196F3', # 蓝色 '-gravity', 'North', '-annotate', '+0+80', '技术资讯', output_file ] subprocess.run(title_cmd, check=True) # 添加文章标题 title_lines = self._split_text(title, 35) for i, line in enumerate(title_lines[:2]): y_offset = 180 + i * 45 text_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '26', '-fill', '#333333', '-gravity', 'Center', '-annotate', f'+0+{y_offset}', line, output_file ] subprocess.run(text_cmd, check=True) # 添加底部信息 info_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '18', '-fill', '#666666', '-gravity', 'South', '-annotate', '+0+80', f'{source} • {datetime.now().strftime("%Y-%m-%d")}', output_file ] subprocess.run(info_cmd, check=True) print(f"✅ 极简风格图片创建成功: {output_file}") return output_file except Exception as e: print(f"❌ 创建极简风格图片失败: {e}") return self._create_fallback_image(title, source, output_file) def _create_gradient_style(self, title, source, output_file): """渐变风格图片""" try: # 创建渐变背景 cmd = [ 'convert', '-size', '800x600', 'gradient:#1565C0-#0D47A1', # 蓝色渐变 '-fill', 'white', output_file ] subprocess.run(cmd, check=True) # 添加技术图标 icon_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '80', '-fill', 'rgba(255,255,255,0.2)', '-gravity', 'Center', '-annotate', '+0+0', '💻', output_file ] subprocess.run(icon_cmd, check=True) # 添加标题 title_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans-Bold', '-pointsize', '34', '-fill', 'white', '-gravity', 'Center', '-annotate', '+0-100', '技术前沿', output_file ] subprocess.run(title_cmd, check=True) # 添加文章标题 title_lines = self._split_text(title, 25) for i, line in enumerate(title_lines[:2]): y_offset = -20 + i * 45 text_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '22', '-fill', 'white', '-gravity', 'Center', '-annotate', f'+0+{y_offset}', line, output_file ] subprocess.run(text_cmd, check=True) # 添加来源 source_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '18', '-fill', 'rgba(255,255,255,0.8)', '-gravity', 'South', '-annotate', '+0+100', f'来源: {source}', output_file ] subprocess.run(source_cmd, check=True) print(f"✅ 渐变风格图片创建成功: {output_file}") return output_file except Exception as e: print(f"❌ 创建渐变风格图片失败: {e}") return self._create_fallback_image(title, source, output_file) def _create_tech_style(self, title, source, output_file): """科技风格图片""" try: # 创建科技感背景 cmd = [ 'convert', '-size', '800x600', 'xc:#0a192f', # 深科技蓝 '-fill', '#64ffda', # 科技绿 output_file ] subprocess.run(cmd, check=True) # 添加网格线 grid_cmd = [ 'convert', output_file, '-stroke', 'rgba(100,255,218,0.1)', '-strokewidth', '1', '-draw', 'rectangle 50,50 750,550', '-draw', 'line 400,50 400,550', '-draw', 'line 50,300 750,300', output_file ] subprocess.run(grid_cmd, check=True) # 添加二进制代码背景 binary_bg = [ 'convert', output_file, '-font', 'DejaVu-Sans-Mono', '-pointsize', '14', '-fill', 'rgba(100,255,218,0.05)', '-gravity', 'Center', '-annotate', '+0+0', '01010101\n10101010\n01010101', output_file ] subprocess.run(binary_bg, check=True) # 添加主标题 main_title = [ 'convert', output_file, '-font', 'DejaVu-Sans-Bold', '-pointsize', '28', '-fill', '#64ffda', '-gravity', 'North', '-annotate', '+0+80', 'TECH NEWS', output_file ] subprocess.run(main_title, check=True) # 添加文章标题 title_lines = self._split_text(title, 30) for i, line in enumerate(title_lines[:3]): y_offset = 150 + i * 35 text_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans', '-pointsize', '20', '-fill', '#ccd6f6', '-gravity', 'NorthWest', '-annotate', f'+100+{y_offset}', line, output_file ] subprocess.run(text_cmd, check=True) # 添加底部信息 info_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans-Mono', '-pointsize', '16', '-fill', '#8892b0', '-gravity', 'SouthWest', '-annotate', '+100+80', f'SOURCE: {source}', output_file ] subprocess.run(info_cmd, check=True) time_cmd = [ 'convert', output_file, '-font', 'DejaVu-Sans-Mono', '-pointsize', '16', '-fill', '#8892b0', '-gravity', 'SouthEast', '-annotate', '+100+80', f'TIME: {datetime.now().strftime("%H:%M:%S")}', output_file ] subprocess.run(time_cmd, check=True) print(f"✅ 科技风格图片创建成功: {output_file}") return output_file except Exception as e: print(f"❌ 创建科技风格图片失败: {e}") return self._create_fallback_image(title, source, output_file) def _create_fallback_image(self, title, source, output_file): """回退图片(最简单的图片)""" try: cmd = [ 'convert', '-size', '800x600', 'xc:#2196F3', # 蓝色背景 '-fill', 'white', '-pointsize', '30', '-gravity', 'Center', '-draw', f'text 0,0 "{title[:50]}"', '-pointsize', '20', '-draw', f'text 0,100 "来源: {source}"', output_file ] subprocess.run(cmd, check=True) print(f"✅ 回退图片创建成功: {output_file}") return output_file except Exception as e: print(f"❌ 回退图片也失败: {e}") return None def _split_text(self, text, max_length): """分割文本为多行""" words = text.split() lines = [] current_line = [] for word in words: if len(' '.join(current_line + [word])) <= max_length: current_line.append(word) else: if current_line: lines.append(' '.join(current_line)) current_line = [word] if current_line: lines.append(' '.join(current_line)) return lines def create_image_from_article(self, article_data, style="modern"): """从文章数据创建图片""" title = article_data.get('title', '技术资讯') source = article_data.get('source', 'IT资讯') content_preview = article_data.get('content_preview') return self.create_tech_news_image(title, source, content_preview, style) def test_image_generator(): """测试图片生成器""" print("🧪 测试图片生成器...") generator = AdvancedImageGenerator() # 测试数据 test_article = { 'title': 'Elastic Releases Version 9.3.0 With Enhanced AI Tools and OTel Support', 'source': 'InfoQ', 'content_preview': 'Elastic发布了9.3.0版本,增强了AI工具和OTel支持...' } # 测试不同风格 styles = ['modern', 'minimal', 'gradient', 'tech'] for style in styles: print(f"\n测试 {style} 风格...") image_path = generator.create_tech_news_image( test_article['title'], test_article['source'], test_article['content_preview'], style ) if image_path: print(f"✅ 图片: {image_path}") # 显示图片信息 subprocess.run(['ls', '-la', image_path]) else: print(f"❌ 创建失败") if __name__ == "__main__": test_image_generator()