Files
nanocode/skills/xiaohongshu_integration/advanced_image_generator.py
T
Ubuntu 32b43f85bd a
2026-07-03 16:58:28 +08:00

455 lines
15 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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()