fix: content quality, image format, task monitor, calendar data source, search UI & sort

This commit is contained in:
Yuzhiran Dev
2026-05-26 11:26:10 +08:00
parent b2d043b231
commit ac8644d752
36 changed files with 2294 additions and 873 deletions
+145 -19
View File
@@ -35,6 +35,28 @@ PLATFORM_RULES = {
}
}
# AI 套话检测模式(一旦出现在正文中,说明写作痕迹明显)
AI_TELTALES = [
"说回到",
"一个真实的.*案例很能说明问题",
"这就是.*被.*后的样子",
"如果你也",
"值得注意的是",
"首先其次最后",
"综上所述",
"总的来说",
"说到这里",
"我们来总结一下",
"总而言之",
"我们不难发现",
"我们可以看出",
"从以上分析可以看出",
"无可否认",
"众所周知",
"毋庸置疑",
"不知大家有没有发现",
]
_cached_sensitive_words = None
_cached_platform_rules = None
@@ -139,15 +161,22 @@ class ComplianceChecker:
# 6. 最小字数检查
self._check_min_length(text, platform)
# 7. 结构完整性检查(必须包含关键章节)
self._check_required_sections(text)
# 7. 内容质量检查
self._check_ai_telltales(text)
self._check_pronoun_consistency(text, platform)
self._check_reading_experience(text, platform)
self._check_platform_engagement(text, platform)
self._check_inline_images(text)
self._check_timeliness(text)
hard_types = ('敏感词', '法律法规', '平台规则', '品牌规范', '资源合规')
hard_issues = [i for i in self.issues if i['type'] in hard_types]
return {
"passed": len(self.issues) == 0,
"passed": len(hard_issues) == 0,
"issues": self.issues,
"score": max(0, 100 - len(self.issues) * 10)
"score": max(0, 100 - sum(
10 if i['type'] in hard_types else 5 for i in self.issues
))
}
def _check_sensitive_words(self, text: str):
@@ -317,23 +346,120 @@ class ComplianceChecker:
"suggestion": "扩写内容至最低要求"
})
def _check_required_sections(self, text: str):
"""检查是否包含必要章节(如引言、核心观点、总结等)"""
required_headings = [
"引言", "核心观点", "受众痛点", "总结", "行动指南"
]
missing = []
for heading in required_headings:
# 检查 h2 或 h3 中是否出现 heading
if not re.search(r'<h[23][^>]*>.*' + re.escape(heading) + r'.*</h[23]>', text, re.IGNORECASE):
missing.append(heading)
if missing:
def _check_ai_telltales(self, text: str):
"""检查AI套话——正文中出现这些模式说明AI写作痕迹明显"""
plain = re.sub(r'<[^>]+>', '', text)
for pattern in AI_TELTALES:
if re.search(pattern, plain):
self.issues.append({
"type": "内容质量",
"category": "AI套话",
"detail": f"正文出现AI套话模式: 「{pattern}",
"suggestion": "删除或替换为自然表达,不要让读者感觉是AI写的"
})
def _check_pronoun_consistency(self, text: str, platform: str):
"""检查人称一致性(尤其是微信文章)"""
if platform != "wechat":
return
plain = re.sub(r'<[^>]+>', '', text)
has_ni = '' in plain
has_nimen = '你们' in plain
has_women = '我们' in plain
if has_nimen and has_ni:
self.issues.append({
"type": "结构完整",
"category": "章节缺失",
"detail": f"缺少必要章节:{', '.join(missing)}",
"suggestion": "补充缺失章节"
"type": "内容质量",
"category": "人称混用",
"detail": "微信文章中同时使用「你」和「你们」,建议统一为「你」",
"suggestion": "将所有「你们」替换为「你」,保持与读者的单数对话感"
})
if has_women and has_ni:
self.issues.append({
"type": "内容质量",
"category": "人称混用",
"detail": "微信文章中同时使用「我们」和「你」,建议统一视角",
"suggestion": "将「我们」替换为「你」或「我」,保持与读者对话而非说教"
})
def _check_reading_experience(self, text: str, platform: str = ""):
"""检查阅读体验(段落长度、配图)"""
paragraphs = re.findall(r'<p>(.*?)</p>', text, re.DOTALL)
long_paras = [p for p in paragraphs if len(p) > 300]
if len(long_paras) > len(paragraphs) * 0.3:
self.issues.append({
"type": "内容质量",
"category": "段落过长",
"detail": f"超过30%的段落长度>300字(共{len(paragraphs)}段,{len(long_paras)}段过长),在手机上阅读体验差",
"suggestion": "将长段拆分为2-3个短段,每段不超过150-200字"
})
# 图片检测(各平台阈值不同)
imgs = re.findall(r'<img', text)
min_imgs = {"zhihu": 1, "wechat": 1, "xiaohongshu": 1}.get(platform, 1)
if not imgs:
self.issues.append({
"type": "内容质量",
"category": "缺少配图",
"detail": "正文中没有图片,建议插入配图提升阅读体验",
"suggestion": "在关键位置插入配图(数据截图、金句卡片、操作步骤图等)"
})
elif len(imgs) < min_imgs:
self.issues.append({
"type": "内容质量",
"category": "配图不足",
"detail": f"只有{len(imgs)}张图,建议至少{min_imgs}张配图提升阅读体验",
"suggestion": "在文章中间部分增加配图"
})
def _check_platform_engagement(self, text: str, platform: str):
"""检查平台特有的互动/传播要素"""
plain = re.sub(r'<[^>]+>', '', text)
if platform == "zhihu":
# 知乎需要讨论引导(评论区互动是核心算法权重)
if not any(kw in plain for kw in ('你觉得', '你怎么看', '欢迎在评论区', '说说你的', '欢迎讨论', '你怎么想')):
self.issues.append({
"type": "内容质量",
"category": "缺少互动引导",
"detail": "知乎文章建议在末尾加讨论引导(如「你觉得呢?欢迎在评论区聊聊」),提升互动率",
"suggestion": "在文章末尾添加一个问题或讨论话题,引导读者评论"
})
# 检查是否有数据引用(知乎读者看重可信度)
if not any(kw in plain for kw in ('据统计', '调研显示', '数据显示', '报告指出', '根据', '研究表明', '调查显示')):
self.issues.append({
"type": "内容质量",
"category": "缺少数据引用",
"detail": "知乎文章建议引用具体数据或报告来支撑观点,增强可信度",
"suggestion": "在关键观点处引用权威数据来源"
})
if platform == "xiaohongshu":
# 小红书需要收藏引导(收藏率是推荐算法核心指标)
if '收藏' not in plain:
self.issues.append({
"type": "内容质量",
"category": "缺少收藏引导",
"detail": "小红书笔记建议在末尾加收藏引导(如「觉得有用点个收藏」),提升收藏率",
"suggestion": "在末尾添加收藏引导语"
})
# 小红书段落需非常短
paragraphs = re.findall(r'<p>(.*?)</p>', text, re.DOTALL)
long_paras = [p for p in paragraphs if len(p) > 150]
if len(long_paras) > len(paragraphs) * 0.2:
self.issues.append({
"type": "内容质量",
"category": "段落过长",
"detail": f"小红书建议每段不超过80-100字,当前{len(long_paras)}/{len(paragraphs)}段超过150字",
"suggestion": "将长段拆分为1-2句的短段落,每段不超过100字"
})
# 小红书需要至少一些 emoji
if not re.search(r'[\U0001F300-\U0001F9FF\u2600-\u27BF]', plain):
self.issues.append({
"type": "内容质量",
"category": "缺少emoji",
"detail": "小红书笔记建议适当使用emoji来增加视觉吸引力",
"suggestion": "在标题、章节分隔或重点句前添加相关emoji"
})
def _check_inline_images(self, html: str):
"""检查图片是否以内联方式嵌入(data:image)"""
# 提取所有 img 标签的 src 属性值