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

462 lines
16 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
"""
基于 oh-my-writing-skill 的小红书内容转换器
将通用文章转换为适合小红书平台的格式和风格
"""
import re
import json
import random
from typing import Dict, List, Optional
from dataclasses import dataclass
@dataclass
class XiaohongshuContent:
"""小红书内容结构"""
title: str
content: str
cover_suggestions: List[str]
tags: List[str]
style: str = "小红书风格"
class OhMyWritingConverter:
"""oh-my-writing-skill 内容转换器"""
def __init__(self):
# 小红书用户画像
self.user_profile = {
'main_users': '18-35岁女性为主(男性用户增长中)',
'reading_habit': '刷图文、看封面、快速浏览',
'content_preference': '生活分享、实用攻略、颜值内容',
'interaction_habit': '收藏实用内容、点赞喜欢的博主'
}
# 内容调性
self.content_style = {
'亲切感': '像朋友聊天,不是教科书',
'真实感': '真实体验分享,不是广告',
'实用性': '能带走干货,有收藏价值',
'视觉感': '排版清爽,重点突出'
}
# Emoji映射表
self.emoji_mapping = {
'技术': '💻',
'AI': '🤖',
'编程': '👨‍💻',
'效率': '⚡',
'工具': '🛠️',
'学习': '📚',
'分享': '📢',
'教程': '📝',
'新闻': '📰',
'分析': '📊',
'总结': '📌',
'推荐': '⭐',
'提示': '💡',
'警告': '⚠️',
'成功': '✅',
'错误': '❌',
'问题': '❓',
'答案': '💬',
'收藏': '❤️',
'点赞': '👍',
'关注': '👀'
}
# 语气转换表
self.tone_conversion = {
'本文将介绍': '今天来聊聊',
'建议用户': '建议大家/姐妹们',
'该产品性能优秀': '这个真的很好用!',
'综上所述': '总之就是',
'首先、其次、最后': '第一、第二、第三',
'值得注意的是': '划重点!',
'需要指出的是': '这里要注意',
'根据研究显示': '我发现',
'一般来说': '通常来说',
'具体来说': '具体来说',
'换句话说': '简单说就是',
'例如': '比如',
'此外': '另外',
'然而': '不过',
'因此': '所以',
'最终': '最后'
}
def analyze_content(self, content: str) -> Dict:
"""分析内容特征"""
analysis = {
'length': len(content),
'paragraphs': len(content.split('\n\n')),
'has_images': bool(re.search(r'!\[.*?\]\(.*?\)', content)),
'has_headings': bool(re.search(r'^#+\s+', content, re.MULTILINE)),
'has_lists': bool(re.search(r'^[\-\*\+]\s+', content, re.MULTILINE)),
'formal_tone': 0,
'keywords': []
}
# 检测正式语气
for formal_word in ['本文将', '建议', '该', '综上所述', '需要指出']:
if formal_word in content:
analysis['formal_tone'] += 1
# 提取关键词
words = re.findall(r'\b[\u4e00-\u9fa5]{2,4}\b', content)
from collections import Counter
analysis['keywords'] = [word for word, count in Counter(words).most_common(10)]
return analysis
def optimize_title(self, original_title: str, keywords: List[str]) -> str:
"""优化标题为小红书风格"""
# 移除过于正式的前缀
title = original_title
formal_prefixes = ['关于', '浅谈', '简析', '探讨', '研究', '分析', '报告']
for prefix in formal_prefixes:
if title.startswith(prefix):
title = title[len(prefix):].strip()
# 添加emoji
emoji_to_add = []
for keyword in keywords:
if keyword in self.emoji_mapping:
emoji_to_add.append(self.emoji_mapping[keyword])
break
# 小红书标题特点:简短有力,制造好奇
if len(title) > 20:
# 截断并添加省略号或感叹
title = title[:18] + '...'
# 添加数字/对比增强吸引力
if any(word in title for word in ['方法', '技巧', '工具', '步骤']):
if '个' not in title and '种' not in title:
title = f"这{random.choice(['几', '5', '7', '10'])}个{title}"
# 添加emoji(最多2个)
if emoji_to_add:
title += ' ' + ' '.join(emoji_to_add[:2])
return title
def convert_tone(self, text: str) -> str:
"""转换语气为小红书风格"""
converted = text
# 替换正式表达
for formal, informal in self.tone_conversion.items():
converted = converted.replace(formal, informal)
# 添加亲切称呼
if '大家' in converted or '你们' in converted:
if '姐妹们' not in converted and '家人们' not in converted:
# 随机选择亲切称呼
greetings = ['姐妹们', '家人们', '朋友们', '宝子们']
greeting = random.choice(greetings)
# 在开头添加
lines = converted.split('\n')
if lines and len(lines[0]) < 50:
lines[0] = f"{greeting}!{lines[0]}"
converted = '\n'.join(lines)
return converted
def format_opening(self, content_analysis: Dict) -> str:
"""生成小红书风格开头"""
openings = [
"姐妹们!是不是经常遇到这个问题",
"家人们,今天分享一个超实用的技巧",
"朋友们,我发现了一个宝藏方法",
"宝子们,这个真的太好用了",
"亲测有效,分享给你们",
"用了这个方法,效率直接翻倍",
"之前一直困扰的问题,终于解决了",
"无意间发现的,没想到这么好用"
]
opening = random.choice(openings)
# 根据内容类型调整
if content_analysis['formal_tone'] > 3:
opening = "之前觉得很难,其实掌握了方法很简单"
return f"{opening}\n\n往下看 ⬇️\n\n"
def format_body(self, content: str) -> str:
"""格式化正文为小红书风格"""
# 分割段落
paragraphs = content.split('\n\n')
formatted_paragraphs = []
for i, para in enumerate(paragraphs):
if not para.strip():
continue
# 处理标题
if para.startswith('#'):
level = len(re.match(r'#+', para).group())
title_text = re.sub(r'^#+\s+', '', para).strip()
if level == 1:
# 一级标题转换为【要点】
formatted_para = f"【{title_text}】\n\n"
elif level == 2:
# 二级标题转换为加粗
formatted_para = f"**{title_text}**\n\n"
else:
formatted_para = f"{title_text}\n\n"
# 处理列表
elif re.match(r'^[\-\*\+]\s+', para):
lines = para.split('\n')
formatted_lines = []
for line in lines:
if re.match(r'^[\-\*\+]\s+', line):
# 替换列表符号
line = re.sub(r'^[\-\*\+]\s+', '• ', line)
formatted_lines.append(line)
else:
formatted_lines.append(line)
formatted_para = '\n'.join(formatted_lines) + '\n\n'
# 处理普通段落
else:
# 缩短长段落
if len(para) > 150:
sentences = re.split(r'[。!?]', para)
para = '。'.join(sentences[:3]) + '。'
formatted_para = para + '\n\n'
# 转换语气
formatted_para = self.convert_tone(formatted_para)
# 添加分隔符(每隔2-3段)
if i > 0 and i % random.randint(2, 3) == 0:
formatted_para = f"—————\n\n{formatted_para}"
formatted_paragraphs.append(formatted_para)
return ''.join(formatted_paragraphs)
def format_ending(self, keywords: List[str]) -> str:
"""生成小红书风格结尾"""
endings = [
"有用的话记得收藏 📌",
"有问题评论区见~",
"用过的来聊聊体验",
"你们有什么好方法也分享下",
"下期想看什么内容?",
"关注我,分享更多实用技巧"
]
import random
ending = random.choice(endings)
# 生成标签
tags = []
for keyword in keywords[:5]:
tags.append(f"#{keyword}")
# 添加通用标签
general_tags = ['#干货分享', '#实用技巧', '#自我提升']
tags.extend(general_tags[:3-len(tags)])
return f"\n—————\n\n{ending}\n\n{' '.join(tags)}"
def suggest_cover(self, title: str, keywords: List[str]) -> List[str]:
"""建议封面图元素"""
suggestions = []
# 基本建议
suggestions.append("3:4 竖版比例,高清不模糊")
suggestions.append("简洁干净的设计风格")
# 根据内容类型建议
if any(kw in keywords for kw in ['技术', '编程', 'AI']):
suggestions.append("科技感配色:蓝色/紫色渐变")
suggestions.append("可加入代码片段或芯片图案")
elif any(kw in keywords for kw in ['学习', '教程', '方法']):
suggestions.append("教育感配色:绿色/黄色")
suggestions.append("可加入书本或笔记元素")
elif any(kw in keywords for kw in ['工具', '效率', '技巧']):
suggestions.append("高效感配色:橙色/红色")
suggestions.append("可加入齿轮或闪电元素")
# 文字建议
short_title = title[:15] + '...' if len(title) > 15 else title
suggestions.append(f"封面文字:{short_title}")
return suggestions
def convert_to_xiaohongshu(self, original_content: str, original_title: str = "") -> XiaohongshuContent:
"""将通用内容转换为小红书格式"""
# 分析内容
analysis = self.analyze_content(original_content)
# 优化标题
if not original_title:
# 从内容中提取标题
title_match = re.search(r'^#\s+(.+)$', original_content, re.MULTILINE)
original_title = title_match.group(1) if title_match else "实用分享"
optimized_title = self.optimize_title(original_title, analysis['keywords'])
# 构建小红书内容
xhs_content = ""
# 添加开头
xhs_content += self.format_opening(analysis)
# 添加正文
body_content = self.format_body(original_content)
xhs_content += body_content
# 添加结尾
xhs_content += self.format_ending(analysis['keywords'])
# 建议封面
cover_suggestions = self.suggest_cover(optimized_title, analysis['keywords'])
# 生成标签
tags = analysis['keywords'][:5]
return XiaohongshuContent(
title=optimized_title,
content=xhs_content,
cover_suggestions=cover_suggestions,
tags=tags
)
def test_conversion(self, test_content: str = None):
"""测试转换功能"""
if not test_content:
test_content = """# AI写作工具使用指南
随着人工智能技术的发展,AI写作工具已经成为内容创作者的重要助手。本文将介绍几款主流的AI写作工具及其使用技巧。
## 一、Claude
Claude是Anthropic公司开发的AI助手,在中文写作方面表现优异。
主要特点:
- 长文写作能力强,不易跑题
- 改写润色自然,符合中文表达习惯
- 上下文理解准确
使用建议:适合撰写报告、文章、邮件等正式内容。
## 二、ChatGPT
ChatGPT是OpenAI开发的对话式AI,创意丰富。
主要特点:
- 创意点子多,适合头脑风暴
- 插件生态丰富,功能扩展性强
- 多语言支持良好
使用建议:适合创意写作、问题解答、代码编写。
## 三、Notion AI
Notion AI集成在Notion笔记应用中,与工作流结合紧密。
主要特点:
- 与笔记完美结合,整理内容方便
- 翻译总结快速准确
- 模板丰富,开箱即用
使用建议:适合知识管理、内容整理、团队协作。
## 总结
不同的AI写作工具各有优势,建议根据具体需求选择合适的工具。对于正式写作,推荐使用Claude;对于创意工作,推荐使用ChatGPT;对于知识管理,推荐使用Notion AI。"""
print("🧪 测试内容转换...")
print("=" * 60)
# 执行转换
result = self.convert_to_xiaohongshu(test_content)
print(f"📝 原标题: AI写作工具使用指南")
print(f"🎯 小红书标题: {result.title}")
print("\n📱 小红书内容:")
print("=" * 60)
print(result.content)
print("=" * 60)
print("\n🖼️ 封面建议:")
for suggestion in result.cover_suggestions:
print(f" • {suggestion}")
print(f"\n🏷️ 标签: {' '.join([f'#{tag}' for tag in result.tags])}")
return result
def main():
"""主函数"""
import argparse
parser = argparse.ArgumentParser(description='oh-my-writing-skill 小红书转换器')
subparsers = parser.add_subparsers(dest='command', help='命令')
# test命令
subparsers.add_parser('test', help='测试转换功能')
# convert命令
convert_parser = subparsers.add_parser('convert', help='转换内容')
convert_parser.add_argument('--input', required=True, help='输入文件路径')
convert_parser.add_argument('--output', help='输出文件路径')
# analyze命令
analyze_parser = subparsers.add_parser('analyze', help='分析内容')
analyze_parser.add_argument('--input', required=True, help='输入文件路径')
args = parser.parse_args()
converter = OhMyWritingConverter()
if args.command == 'test':
converter.test_conversion()
elif args.command == 'convert':
with open(args.input, 'r', encoding='utf-8') as f:
content = f.read()
# 提取标题
title_match = re.search(r'^#\s+(.+)$', content, re.MULTILINE)
title = title_match.group(1) if title_match else ""
result = converter.convert_to_xiaohongshu(content, title)
if args.output:
with open(args.output, 'w', encoding='utf-8') as f:
f.write(f"# {result.title}\n\n")
f.write(result.content)
f.write("\n\n## 封面建议\n")
for suggestion in result.cover_suggestions:
f.write(f"- {suggestion}\n")
f.write(f"\n## 标签\n{' '.join([f'#{tag}' for tag in result.tags])}\n")
print(f"✅ 转换完成,已保存到: {args.output}")
else:
print(f"🎯 标题: {result.title}")
print("\n📱 内容:")
print(result.content)
elif args.command == 'analyze':
with open(args.input, 'r', encoding='utf-8') as f:
content = f.read()
analysis = converter.analyze_content(content)
print("📊 内容分析结果:")
print(json.dumps(analysis, indent=2, ensure_ascii=False))
else:
parser.print_help()
if __name__ == "__main__":
main()