383 lines
14 KiB
Python
383 lines
14 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
小红书内容转换器 - 修复版
|
||
专门处理IT资讯自动化系统生成的Markdown文件
|
||
"""
|
||
|
||
import re
|
||
import logging
|
||
from typing import Dict, List, Optional, Tuple
|
||
from dataclasses import dataclass
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
@dataclass
|
||
class Article:
|
||
"""文章数据结构"""
|
||
title: str
|
||
content: str
|
||
source: str = ""
|
||
url: str = ""
|
||
keywords: List[str] = None
|
||
|
||
def __post_init__(self):
|
||
if self.keywords is None:
|
||
self.keywords = []
|
||
|
||
@dataclass
|
||
class XiaohongshuContent:
|
||
"""小红书内容结构"""
|
||
title: str
|
||
content: str
|
||
cover_suggestions: List[str] = None
|
||
tags: List[str] = None
|
||
|
||
def __post_init__(self):
|
||
if self.cover_suggestions is None:
|
||
self.cover_suggestions = []
|
||
if self.tags is None:
|
||
self.tags = []
|
||
|
||
class ContentConverterFixed:
|
||
"""修复版内容转换器"""
|
||
|
||
def __init__(self, config: Optional[Dict] = None):
|
||
self.config = config or {}
|
||
logger.info("修复版内容转换器初始化完成")
|
||
|
||
def parse_markdown(self, markdown_content: str) -> Article:
|
||
"""
|
||
解析Markdown文件,提取真正的文章内容
|
||
|
||
Args:
|
||
markdown_content: Markdown文件内容
|
||
|
||
Returns:
|
||
文章对象
|
||
"""
|
||
lines = markdown_content.split('\n')
|
||
|
||
# 提取标题(第一行)
|
||
title = ""
|
||
if lines and lines[0].startswith('# '):
|
||
title = lines[0][2:].strip()
|
||
|
||
# 查找文章内容部分
|
||
content_start = -1
|
||
for i, line in enumerate(lines):
|
||
if line.strip() == "## 📰 文章内容(DeepSeek翻译)":
|
||
content_start = i + 1
|
||
break
|
||
|
||
# 提取真正的文章内容 - 修复:只提取DeepSeek翻译的正文
|
||
content_lines = []
|
||
if content_start > 0:
|
||
# 跳过空行和可能的标题标记行
|
||
i = content_start
|
||
while i < len(lines):
|
||
line = lines[i].strip()
|
||
# 跳过空行和标题标记行
|
||
if not line or line.startswith('**标题:') or line.startswith('**核心内容翻译:'):
|
||
i += 1
|
||
continue
|
||
# 找到真正的内容开始
|
||
break
|
||
|
||
# 收集真正的文章内容(直到下一个##标题或---分隔符)
|
||
while i < len(lines):
|
||
line = lines[i]
|
||
# 如果遇到下一个标题或分隔符,停止收集
|
||
if line.startswith('## ') or line.strip() == '---':
|
||
break
|
||
content_lines.append(line)
|
||
i += 1
|
||
|
||
# 如果还是没有找到,尝试查找中文内容
|
||
if not content_lines:
|
||
for i, line in enumerate(lines):
|
||
# 查找典型的中文内容开始
|
||
if '本文报道了' in line or '文章指出' in line or '主要观点' in line:
|
||
# 从这个段落开始收集
|
||
j = i
|
||
while j < len(lines) and not lines[j].startswith('## ') and lines[j].strip() != '---':
|
||
if lines[j].strip():
|
||
content_lines.append(lines[j])
|
||
j += 1
|
||
break
|
||
|
||
# 如果还是没有,使用整个内容
|
||
if not content_lines:
|
||
content_lines = lines
|
||
|
||
content = '\n'.join(content_lines).strip()
|
||
|
||
# 提取来源
|
||
source = ""
|
||
for line in lines:
|
||
if "**来源**:" in line or "来源:" in line:
|
||
match = re.search(r'[::]\s*(.+)', line)
|
||
if match:
|
||
source = match.group(1).strip()
|
||
break
|
||
|
||
# 提取原文链接
|
||
url = ""
|
||
for line in lines:
|
||
if "原文链接:" in line or "**原文链接**:" in line:
|
||
match = re.search(r'https?://[^\s]+', line)
|
||
if match:
|
||
url = match.group(0).strip()
|
||
break
|
||
|
||
return Article(
|
||
title=title,
|
||
content=content,
|
||
source=source,
|
||
url=url
|
||
)
|
||
|
||
def extract_main_content(self, content: str) -> str:
|
||
"""
|
||
从文章内容中提取核心部分
|
||
|
||
Args:
|
||
content: 原始文章内容
|
||
|
||
Returns:
|
||
提取后的核心内容
|
||
"""
|
||
# 移除标题行
|
||
lines = content.split('\n')
|
||
filtered_lines = []
|
||
|
||
for line in lines:
|
||
# 跳过空行和标题行
|
||
if not line.strip():
|
||
continue
|
||
if line.startswith('**标题:'):
|
||
continue
|
||
if line.startswith('**核心内容翻译:'):
|
||
continue
|
||
if line.startswith('---'):
|
||
continue
|
||
|
||
filtered_lines.append(line)
|
||
|
||
return '\n\n'.join(filtered_lines)
|
||
|
||
def to_xiaohongshu_basic(self, article: Article) -> str:
|
||
"""
|
||
基础转换:将文章转换为小红书格式
|
||
|
||
Args:
|
||
article: 文章对象
|
||
|
||
Returns:
|
||
小红书格式的内容
|
||
"""
|
||
# 提取核心内容
|
||
main_content = self.extract_main_content(article.content)
|
||
|
||
# 处理标题
|
||
title = self._process_title(article.title)
|
||
|
||
# 构建小红书内容
|
||
xhs_content = ""
|
||
|
||
# 开头
|
||
xhs_content += f"姐妹们!今天分享一个超实用的技术资讯\n\n"
|
||
xhs_content += f"往下看 ⬇️\n\n"
|
||
|
||
# 标题
|
||
xhs_content += f"【{title}】\n\n"
|
||
|
||
# 来源
|
||
if article.source:
|
||
xhs_content += f"来源: {article.source}\n\n"
|
||
xhs_content += "—————\n\n"
|
||
|
||
# 核心内容(限制长度)
|
||
if main_content:
|
||
# 限制内容长度(小红书适合短内容)
|
||
if len(main_content) > 800:
|
||
# 取前800字符,并在完整句子处截断
|
||
truncated = main_content[:800]
|
||
last_period = max(
|
||
truncated.rfind('。'),
|
||
truncated.rfind('!'),
|
||
truncated.rfind('?'),
|
||
truncated.rfind('.')
|
||
)
|
||
if last_period > 600: # 确保有足够内容
|
||
main_content = truncated[:last_period + 1]
|
||
else:
|
||
main_content = truncated + "..."
|
||
|
||
xhs_content += f"{main_content}\n\n"
|
||
|
||
# 结尾
|
||
xhs_content += "—————\n\n"
|
||
xhs_content += "有用的话记得收藏 📌\n\n"
|
||
|
||
# 标签
|
||
tags = self._generate_tags(article)
|
||
xhs_content += f"{tags}\n\n"
|
||
|
||
# 互动提示
|
||
xhs_content += "💬 你对这个话题有什么看法?欢迎在评论区讨论!\n"
|
||
xhs_content += "⭐ 如果觉得有用,记得点赞收藏哦~\n\n"
|
||
|
||
# 原文链接
|
||
if article.url:
|
||
xhs_content += f"🔗 原文链接: {article.url}"
|
||
|
||
return xhs_content
|
||
|
||
def _process_title(self, title: str) -> str:
|
||
"""处理标题"""
|
||
# 缩短过长的标题
|
||
if len(title) > 40:
|
||
title = title[:37] + "..."
|
||
return title
|
||
|
||
def _generate_tags(self, article: Article) -> str:
|
||
"""生成标签"""
|
||
base_tags = ["#来源", "#干货分享", "#实用技巧", "#技术资讯", "#科技新闻", "#技术"]
|
||
|
||
# 根据来源添加特定标签
|
||
if "MIT" in article.source or "Technology Review" in article.source:
|
||
base_tags.append("#MIT")
|
||
base_tags.append("#AI技术")
|
||
|
||
if "The Verge" in article.source:
|
||
base_tags.append("#TheVerge")
|
||
base_tags.append("#科技媒体")
|
||
|
||
if "InfoQ" in article.source:
|
||
base_tags.append("#InfoQ")
|
||
base_tags.append("#开发者")
|
||
|
||
return " ".join(base_tags)
|
||
|
||
def convert_markdown_to_xiaohongshu(self, markdown_content: str) -> str:
|
||
"""
|
||
主转换函数:将Markdown文件转换为小红书格式
|
||
|
||
Args:
|
||
markdown_content: Markdown文件内容
|
||
|
||
Returns:
|
||
小红书格式的内容
|
||
"""
|
||
try:
|
||
# 1. 解析Markdown文件
|
||
article = self.parse_markdown(markdown_content)
|
||
|
||
logger.info(f"解析文章: {article.title}")
|
||
logger.info(f"来源: {article.source}")
|
||
logger.info(f"内容长度: {len(article.content)} 字符")
|
||
|
||
# 2. 转换为小红书格式
|
||
xhs_content = self.to_xiaohongshu_basic(article)
|
||
|
||
logger.info(f"转换完成,标题: {article.title[:30]}...")
|
||
return xhs_content
|
||
|
||
except Exception as e:
|
||
logger.error(f"转换失败: {e}")
|
||
|
||
# 回退:简单转换
|
||
lines = markdown_content.split('\n')
|
||
title = lines[0][2:].strip() if lines and lines[0].startswith('# ') else "技术资讯"
|
||
|
||
return f"""姐妹们!今天分享一个技术资讯
|
||
|
||
往下看 ⬇️
|
||
|
||
【{title[:30]}...】
|
||
|
||
来源: IT资讯
|
||
|
||
—————
|
||
|
||
💡 内容处理中遇到问题,请查看原文链接获取完整内容。
|
||
|
||
—————
|
||
|
||
有用的话记得收藏 📌
|
||
|
||
#技术资讯 #科技新闻 #干货分享
|
||
|
||
💬 你对这个话题有什么看法?欢迎在评论区讨论!
|
||
⭐ 如果觉得有用,记得点赞收藏哦~"""
|
||
|
||
|
||
def test_conversion():
|
||
"""测试转换功能"""
|
||
converter = ContentConverterFixed()
|
||
|
||
# 测试内容
|
||
test_md = """# Where OpenAI's technology could show up in Iran
|
||
|
||
## 📋 文章信息
|
||
|
||
- **来源**: MIT Technology Review
|
||
- **原文标题**: Where OpenAI's technology could show up in Iran
|
||
- **原文链接**: https://www.technologyreview.com/2026/03/16/1134315/where-openais-technology-could-show-up-in-iran/
|
||
- **发布日期**: None
|
||
- **原文字数**: 1,227
|
||
- **文章类型**: 技术类
|
||
- **处理方式**: DeepSeek翻译
|
||
- **处理时间**: 2026-03-17 16:01:00
|
||
- **抓取时间**: 2026-03-17T16:00:27.836284
|
||
|
||
---
|
||
|
||
## 📰 文章内容(DeepSeek翻译)
|
||
|
||
**标题:OpenAI技术可能在伊朗战场出现的三个关键领域**
|
||
|
||
**核心内容翻译:**
|
||
|
||
从战争边缘到战斗核心,值得关注的三个领域。
|
||
|
||
OpenAI与五角大楼达成允许其在涉密环境中使用AI技术的争议性协议已逾两周。该协议的具体授权范围仍存紧迫疑问:萨姆·奥尔特曼虽宣称军方不得用其技术开发生化武器,但协议仅要求军方遵循自身()相关准则。OpenAI另一主要声明——协议将禁止其技术用于国内监控——同样显得可疑。
|
||
|
||
OpenAI的动机尚不明确。这并非科技巨头首次违背"永不涉足"的誓言承接军事合同,但其立场转变速度之快值得注意。或许出于资金压力:OpenAI正投入巨资进行AI训练并寻求更多收入来源(包括广告)。亦或奥尔特曼真心信奉其常提及的意识形态框架:自由民主国家(及其军队)必须掌握最强AI以与中国竞争。
|
||
|
||
更关键的问题在于后续发展。随着美国升级对伊朗打击(AI在其中发挥空前作用),OpenAI已决定深入复杂的战斗核心。那么其技术具体可能出现在哪些作战环节?哪些应用会获得客户(及员工)容忍?
|
||
|
||
**目标定位与打击**
|
||
尽管协议已生效,OpenAI技术何时能适配涉密环境仍不确定,因其需与军方现有工具整合(埃隆·马斯克的xAI近期也与五角大楼达成协议,其AI模型Grok预计将经历相同流程)。但整合压力迫在眉睫:在Anthropic拒绝允许其AI用于"任何合法用途"后,特朗普总统下令军方停用该技术,五角大楼更将Anthropic列为供应链风险。
|
||
|
||
**作战平台部署**
|
||
五角大楼去年秋季推出的生成式AI平台GenAI.mil,允许军事单位接入商业AI模型并执行与商业领域类似的任务。谷歌Gemini是首批入驻模型。今年1月五角大楼宣布将纳入xAI的Grok(尽管该模型曾传播反犹内容并生成非自愿深度伪造视频)。OpenAI于2月跟进,宣布其模型将用于起草政策文件、合同及协助任务行政支持。
|
||
|
||
虽然使用该平台处理非密任务的人员对伊朗敏感决策影响有限,但OpenAI入驻具有更深层意义:这呼应了赫格塞斯在五角大楼全力推行的AI全覆盖战略(即便许多早期用户并不完全明确使用场景)。其传递的信号是:AI正在重塑美国作战的每个环节——从目标判定到文书工作,而OpenAI正日益赢得其中份额。
|
||
---
|
||
处理信息: DeepSeek API | 耗时: 14.24秒
|
||
|
||
---
|
||
原文链接: https://www.technologyreview.com/2026/03/16/1134315/where-openais-technology-could-show-up-in-iran/
|
||
处理时间: 2026-03-17 16:01:00
|
||
|
||
|
||
## 🖼️ 文章图片
|
||
|
||
1. 
|
||
*描述: Sam Altman collage*
|
||
"""
|
||
|
||
result = converter.convert_markdown_to_xiaohongshu(test_md)
|
||
|
||
print("=" * 60)
|
||
print("修复版转换器测试结果")
|
||
print("=" * 60)
|
||
print(result)
|
||
print("=" * 60)
|
||
print(f"内容长度: {len(result)} 字符")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
logging.basicConfig(level=logging.INFO)
|
||
test_conversion() |