PyWxDump/test.py

921 lines
38 KiB
Python
Raw Normal View History

import json
import re
def main(json_data):
# 加载模板
html = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>[/用户名称]日报 - [日期]</title>
<style>
/* 严格定义的CSS样式确保风格一致性 */
:root {
--bg-primary: #0f0e17;
--bg-secondary: #1a1925;
--bg-tertiary: #252336;
--text-primary: #fffffe;
--text-secondary: #a7a9be;
--accent-primary: #ff8906;
--accent-secondary: #f25f4c;
--accent-tertiary: #e53170;
--accent-blue: #3da9fc;
--accent-purple: #7209b7;
--accent-cyan: #00b4d8;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'SF Pro Display', 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', sans-serif;
background-color: var(--bg-primary);
color: var(--text-primary);
line-height: 1.6;
font-size: 16px;
width: 1200px;
margin: 0 auto;
padding: 20px;
}
header {
text-align: center;
padding: 30px 0;
background-color: var(--bg-secondary);
margin-bottom: 30px;
}
h1 {
font-size: 36px;
font-weight: 700;
color: var(--accent-primary);
margin-bottom: 10px;
}
.date {
font-size: 18px;
color: var(--text-secondary);
margin-bottom: 20px;
}
.meta-info {
display: flex;
justify-content: center;
gap: 20px;
}
.meta-info span {
background-color: var(--bg-tertiary);
padding: 5px 15px;
border-radius: 20px;
font-size: 14px;
}
section {
background-color: var(--bg-secondary);
margin-bottom: 30px;
padding: 25px;
}
h2 {
font-size: 28px;
font-weight: 600;
color: var(--accent-blue);
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 2px solid var(--accent-blue);
}
h3 {
font-size: 22px;
font-weight: 600;
color: var(--accent-primary);
margin: 15px 0 10px 0;
}
h4 {
font-size: 18px;
font-weight: 600;
color: var(--accent-secondary);
margin: 12px 0 8px 0;
}
p {
margin-bottom: 15px;
}
ul, ol {
margin-left: 20px;
margin-bottom: 15px;
}
li {
margin-bottom: 5px;
}
a {
color: var(--accent-blue);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
/* 卡片容器样式 */
.topics-container, .tutorials-container, .messages-container,
.dialogues-container, .qa-container, .participants-container {
display: grid;
grid-template-columns: 1fr;
gap: 20px;
}
/* 卡片样式 */
.topic-card, .tutorial-card, .message-card,
.dialogue-card, .qa-card, .participant-item, .night-owl-item {
background-color: var(--bg-tertiary);
padding: 20px;
}
/* 话题卡片 */
.topic-category {
display: inline-block;
background-color: var(--accent-blue);
color: var(--text-primary);
padding: 3px 10px;
border-radius: 15px;
font-size: 14px;
margin-bottom: 10px;
}
.topic-keywords {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 10px 0;
}
.keyword {
background-color: rgba(61, 169, 252, 0.2);
padding: 3px 10px;
border-radius: 12px;
font-size: 14px;
}
.topic-mentions {
color: var(--accent-cyan);
font-weight: 600;
}
/* 教程卡片 */
.tutorial-type {
display: inline-block;
background-color: var(--accent-secondary);
color: var(--text-primary);
padding: 3px 10px;
border-radius: 15px;
font-size: 14px;
margin-bottom: 10px;
}
.tutorial-meta {
color: var(--text-secondary);
margin-bottom: 10px;
font-size: 14px;
}
.tutorial-category {
margin-top: 10px;
font-style: italic;
color: var(--text-secondary);
}
/* 消息卡片 */
.message-meta {
margin-bottom: 10px;
}
.message-meta span {
margin-right: 15px;
font-size: 14px;
}
.message-type {
background-color: var(--accent-tertiary);
color: var(--text-primary);
padding: 3px 10px;
border-radius: 15px;
}
.priority {
padding: 3px 10px;
border-radius: 15px;
}
.priority-high {
background-color: var(--accent-secondary);
}
.priority-medium {
background-color: var(--accent-primary);
}
.priority-low {
background-color: var(--accent-blue);
}
/* 对话卡片 */
.dialogue-type {
display: inline-block;
background-color: var(--accent-purple);
color: var(--text-primary);
padding: 3px 10px;
border-radius: 15px;
font-size: 14px;
margin-bottom: 10px;
}
.dialogue-content {
background-color: rgba(255, 255, 255, 0.05);
padding: 15px;
margin-bottom: 15px;
}
.dialogue-highlight {
font-style: italic;
color: var(--accent-primary);
margin: 10px 0;
font-weight: 600;
}
/* 问答卡片 */
.question {
margin-bottom: 15px;
}
.question-meta, .answer-meta {
color: var(--text-secondary);
margin-bottom: 5px;
font-size: 14px;
}
.question-tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}
.tag {
background-color: rgba(114, 9, 183, 0.2);
padding: 3px 10px;
border-radius: 12px;
font-size: 14px;
}
.answer {
background-color: rgba(255, 255, 255, 0.05);
padding: 15px;
margin-top: 10px;
}
.accepted-badge {
background-color: var(--accent-primary);
color: var(--text-primary);
padding: 3px 10px;
border-radius: 15px;
font-size: 14px;
}
/* 热度图 */
.heatmap-container {
display: grid;
grid-template-columns: 1fr;
gap: 15px;
}
.heat-topic {
font-weight: 600;
margin-bottom: 5px;
}
.heat-bar {
height: 20px;
background-color: rgba(255, 255, 255, 0.1);
margin: 5px 0;
border-radius: 10px;
overflow: hidden;
}
.heat-fill {
height: 100%;
border-radius: 10px;
}
/* 话唠榜 */
.participant-rank {
font-size: 28px;
font-weight: 700;
color: var(--accent-primary);
margin-right: 15px;
float: left;
}
.participant-name {
font-weight: 600;
font-size: 18px;
margin-bottom: 5px;
}
.participant-count {
color: var(--accent-cyan);
margin-bottom: 10px;
}
.participant-characteristics, .participant-words {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 10px;
}
.characteristic {
background-color: rgba(242, 95, 76, 0.2);
padding: 3px 10px;
border-radius: 12px;
font-size: 14px;
}
.word {
background-color: rgba(229, 49, 112, 0.2);
padding: 3px 10px;
border-radius: 12px;
font-size: 14px;
}
/* 熬夜冠军 */
.night-owl-item {
background: linear-gradient(135deg, #0f0e17 0%, #192064 100%);
padding: 20px;
display: flex;
align-items: center;
}
.owl-crown {
font-size: 40px;
margin-right: 20px;
}
.owl-name {
font-weight: 600;
font-size: 18px;
margin-bottom: 5px;
}
.owl-title {
color: var(--accent-primary);
font-style: italic;
margin-bottom: 10px;
}
.owl-time, .owl-messages {
color: var(--text-secondary);
margin-bottom: 5px;
}
.owl-note {
font-size: 14px;
color: var(--text-secondary);
margin-top: 10px;
font-style: italic;
}
/* 词云 - 云朵样式 */
.cloud-container {
position: relative;
margin: 0 auto;
padding: 20px 0;
}
.cloud-wordcloud {
position: relative;
width: 600px;
height: 400px;
margin: 0 auto;
background-color: var(--bg-tertiary);
border-radius: 50%;
box-shadow:
40px 40px 0 -5px var(--bg-tertiary),
80px 10px 0 -10px var(--bg-tertiary),
110px 35px 0 -5px var(--bg-tertiary),
-40px 50px 0 -8px var(--bg-tertiary),
-70px 20px 0 -10px var(--bg-tertiary);
overflow: visible;
}
.cloud-word {
position: absolute;
transform-origin: center;
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
transition: all 0.3s ease;
}
.cloud-word:hover {
transform: scale(1.1);
z-index: 10;
}
.cloud-legend {
margin-top: 60px;
display: flex;
justify-content: center;
gap: 30px;
}
.legend-item {
display: flex;
align-items: center;
gap: 10px;
}
.legend-color {
width: 20px;
height: 20px;
border-radius: 50%;
}
/* 底部 */
footer {
text-align: center;
padding: 20px 0;
margin-top: 50px;
background-color: var(--bg-secondary);
color: var(--text-secondary);
font-size: 14px;
}
footer p {
margin: 5px 0;
}
.disclaimer {
margin-top: 15px;
font-style: italic;
}
/* 新增头像相关样式 */
.user-avatar {
width: 50px;
height: 50px;
border-radius: 50%;
object-fit: cover;
transition: transform 0.3s ease;
position: relative;
cursor: pointer;
border: 2px solid var(--accent-primary);
}
/* 头像悬停效果 */
.user-avatar:hover {
transform: scale(1.1) rotate(5deg);
z-index: 100;
}
/* 头像tooltip */
.avatar-tooltip {
visibility: hidden;
background-color: var(--bg-tertiary);
color: var(--text-primary);
text-align: center;
padding: 5px 10px;
border-radius: 6px;
position: absolute;
z-index: 1000;
bottom: 125%;
left: 50%;
transform: translateX(-50%);
white-space: nowrap;
opacity: 0;
transition: opacity 0.3s;
font-size: 14px;
box-shadow: 0 3px 10px rgba(0,0,0,0.2);
}
.user-avatar:hover .avatar-tooltip {
visibility: visible;
opacity: 1;
}
/* 热度用户专区 */
.hot-users {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: 20px;
margin-top: 20px;
}
.hot-user-item {
position: relative;
text-align: center;
}
/* 皇冠标识 */
.hot-crown {
position: absolute;
top: -10px;
right: -5px;
font-size: 24px;
color: #ffd700;
filter: drop-shadow(0 2px 2px rgba(0,0,0,0.3));
}
</style>
</head>
<body>
<header>
<h1>[/用户名称]日报</h1>
<p class="date">[日期]</p>
<div class="meta-info">
<span>总消息数[数量]</span>
<span>活跃用户[数量]</span>
<span>时间范围[时间范围]</span>
</div>
</header>
<!-- 1. 今日讨论热点 -->
<section class="hot-topics">
<h2>今日讨论热点</h2>
<div class="topics-container">
<!-- 在这里填充讨论热点内容严格按照以下格式保留3-5个话题 -->
<!-- 在这里填充讨论热点内容 -->
<!-- 复制上述卡片结构添加更多话题 -->
</div>
</section>
<!-- 2. 实用教程与资源分享 -->
<section class="tutorials">
<h2>实用教程与资源分享</h2>
<div class="tutorials-container">
<!-- 在这里填充教程和资源内容严格按照以下格式 -->
<!-- 在这里填充教程和资源内容 -->
<!-- 复制上述卡片结构添加更多资源 -->
</div>
</section>
<!-- 3. 重要消息汇总 -->
<section class="important-messages">
<h2>重要消息汇总</h2>
<div class="messages-container">
<!-- 在这里填充重要消息内容严格按照以下格式 -->
<!-- 在这里填充重要消息内容 -->
<!-- 复制上述卡片结构添加更多消息 -->
</div>
</section>
<!-- 4. 有趣对话或金句 -->
<section class="interesting-dialogues">
<h2>有趣对话或金句</h2>
<div class="dialogues-container">
<!-- 在这里填充对话内容严格按照以下格式 -->
<!-- 在这里填充对话内容 -->
<!-- 复制上述卡片结构添加更多对话 -->
</div>
</section>
<!-- 5. 问题与解答 -->
<section class="questions-answers">
<h2>问题与解答</h2>
<div class="qa-container">
<!-- 在这里填充问答内容严格按照以下格式 -->
<!-- 在这里填充问答内容 -->
<!-- 复制上述卡片结构添加更多问答 -->
</div>
</section>
<!-- 6. 群内数据可视化 -->
<section class="analytics">
<h2>群内数据可视化</h2>
<!-- 话题热度 -->
<h3>话题热度</h3>
<div class="heatmap-container">
<!-- 在这里填充话题热度数据严格按照以下格式 -->
<!-- 复制上述结构添加更多热度项每项使用不同颜色 -->
<!-- 在这里填充话题热度数据 -->
<!-- 可用的颜色: #3da9fc, #f25f4c, #7209b7, #e53170, #00b4d8, #4cc9f0 -->
</div>
<!-- 话唠榜 -->
<!-- 在话唠榜添加头像 -->
<section class="analytics">
<h3>话唠榜</h3>
<div class="participants-container">
<!-- 在这里填充话唠榜数据 -->
</div>
</section>
<!-- 熬夜冠军 -->
<h3>熬夜冠军</h3>
<div class="night-owls-container">
<!-- 在这里填充熬夜冠军数据严格按照以下格式 -->
<!-- 在这里填充熬夜冠军内容 -->
</div>
</section>
<!-- 7. 词云 -->
<section class="word-cloud">
<h2>热门词云</h2>
<div class="cloud-container">
<!-- 词云容器 - 现在是云朵样式 -->
<div class="cloud-wordcloud" id="word-cloud">
<!-- 为每个词创建一个span元素使用绝对定位放置 -->
<!-- 以下是一些示例请根据实际内容生成40-60个词 -->
<!-- 在这里填充词云内容 -->
<!-- 继续添加更多词 -->
</div>
<div class="cloud-legend">
<!-- 在这里填充词云分类内容 -->
</div>
</div>
</section>
<!-- 8. 页面底部 -->
<footer>
<p>数据来源[群名称]聊天记录</p>
<p>生成时间<span class="generation-time">[当前时间]</span></p>
<p>统计周期[日期] [时间范围]</p>
<p class="disclaimer">免责声明本报告内容基于群聊公开讨论如有不当内容或侵权问题请联系管理员处理</p>
</footer>
</body>
</html>
"""
json_data = json_data[7:-3]
# 清洗json_data
# 判断是否是转义的换行符
if '\n' in json_data:
json_data = json_data.replace('\n', '\n')
else:
json_data = json_data.replace(r'\"','"').replace(r"\n",'\n')
# print(json_data)
# 使用正则表达式查找json字符串
pattern = re.compile('{.*}', flags=re.IGNORECASE | re.MULTILINE | re.S)
print(pattern.search(json_data).group())
json_data = json.loads(pattern.search(json_data).group())
# json_data = json.loads(json_data)
# print(json_data)
# print(json.dumps(json_data,indent=4, ensure_ascii=False))
# 替换头部信息
header = json_data['header']
html = html.replace('[群/用户名称]日报', f"{header['title']}报告")
html = html.replace('[日期]', header['date'])
html = html.replace('总消息数:[数量]', f"总消息数:{header['metaInfo']['totalMessages']}")
html = html.replace('活跃用户:[数量]', f"活跃用户:{header['metaInfo']['activeUsers']}")
html = html.replace('时间范围:[时间范围]', f"时间范围:{header['metaInfo']['timeRange']}")
# 处理热点话题
hot_topics = []
for topic in json_data['sections']['hotTopics']['items']:
keywords = ''.join([f'<span class="keyword">{kw}</span>' for kw in topic['keywords']])
hot_topics.append(f"""
<div class="topic-card">
<h3>{topic['name']}</h3>
<div class="topic-category">{topic['category']}</div>
<p class="topic-summary">{topic['summary']}</p>
<div class="topic-keywords">
{keywords}
</div>
<div class="topic-mentions">提及次数{topic['mentions']}</div>
</div>""")
html = html.replace('<!-- 在这里填充讨论热点内容 -->', '\n'.join(hot_topics))
# 处理教程资源
tutorials = []
for tut in json_data['sections']['tutorials']['items']:
points = ''.join([f'<li>{p}</li>' for p in tut['keyPoints']])
tutorials.append(f"""
<div class="tutorial-card">
<div class="tutorial-type">{tut['type']}</div>
<h3>{tut['title']}</h3>
<div class="tutorial-meta">
<span class="shared-by">分享者{tut['sharedBy']}</span>
<span class="share-time">时间{tut['time']}</span>
</div>
<p class="tutorial-summary">{tut['summary']}</p>
<div class="key-points">
<h4>要点</h4>
<ul>{points}</ul>
</div>
<div class="tutorial-link">
<a href="{tut['url']}" class="link valid">查看原文: {tut['domain']}</a>
</div>
<div class="tutorial-category">分类{tut['category']}</div>
</div>""")
html = html.replace('<!-- 在这里填充教程和资源内容 -->', '\n'.join(tutorials))
# 处理重要消息
messages = []
for msg in json_data['sections']['importantMessages']['items']:
messages.append(f"""
<div class="message-card">
<div class="message-meta">
<span class="time">{msg['time']}</span>
<span class="sender">{msg['sender']}</span>
<span class="message-type">{msg['type']}</span>
<span class="priority priority-{msg['priority']}">优先级{msg['priority']}</span>
</div>
<p class="message-content">{msg['content']}</p>
<div class="message-full-content">
<p>{msg['fullContent']}</p>
</div>
</div>""")
html = html.replace('<!-- 在这里填充重要消息内容 -->', '\n'.join(messages))
# 处理对话
dialogues = []
for dia in json_data['sections']['dialogues']['items']:
messages = ''.join([f"""
<div class="message">
<div class="message-meta">
<span class="speaker">{m['speaker']}</span>
<span class="time">{m['time']}</span>
</div>
<p class="message-content">{m['content']}</p>
</div>""" for m in dia['messages']])
dialogues.append(f"""
<div class="dialogue-card">
<div class="dialogue-type">{dia['type']}</div>
<div class="dialogue-content">
{messages}
</div>
<div class="dialogue-highlight">{dia['highlight']}</div>
<div class="dialogue-topic">相关话题{dia['relatedTopic']}</div>
</div>""")
html = html.replace('<!-- 在这里填充对话内容 -->', '\n'.join(dialogues))
# 处理问答
qas = []
for qa in json_data['sections']['qa']['items']:
tags = ''.join([f'<span class="tag">{tag}</span>' for tag in qa['question']['tags']])
answers = ''.join([f"""
<div class="answer">
<div class="answer-meta">
<span class="responder">{ans['responder']}</span>
<span class="time">{ans['time']}</span>
{"<span class='accepted-badge'>最佳回答</span>" if ans['isAccepted'] else ""}
</div>
<p class="answer-content">{ans['content']}</p>
</div>""" for ans in qa['answers']])
qas.append(f"""
<div class="qa-card">
<div class="question">
<div class="question-meta">
<span class="asker">{qa['question']['asker']}</span>
<span class="time">{qa['question']['time']}</span>
</div>
<p class="question-content">{qa['question']['content']}</p>
<div class="question-tags">
{tags}
</div>
</div>
<div class="answers">
{answers}
</div>
</div>""")
html = html.replace('<!-- 在这里填充问答内容 -->', '\n'.join(qas))
# 处理数据可视化
heatmap = []
colors = ['#3da9fc', '#f25f4c', '#7209b7', '#e53170', '#00b4d8', '#4cc9f0']
for i, topic in enumerate(json_data['sections']['analytics']['heatmap']):
color = colors[i % len(colors)]
heatmap.append(f"""
<div class="heat-item">
<div class="heat-topic">{topic['topic']}</div>
<div class="heat-percentage">{topic['percentage']}%</div>
<div class="heat-bar">
<div class="heat-fill" style="width: {topic['percentage']}%; background-color: {color};"></div>
</div>
<div class="heat-count">{topic['count']}条消息</div>
</div>""")
html = html.replace('<!-- 在这里填充话题热度数据 -->', '\n'.join(heatmap))
# 处理话唠榜
chatty = []
for rank in json_data['sections']['analytics']['chattyRanking']:
words = ''.join([f'<span class="word">{w}</span>' for w in rank['commonWords']])
characteristics = ''.join([f'<span class="characteristic">{c}</span>' for c in rank['characteristics']])
chatty.append(f"""
<div class="participant-item">
<div class="participant-rank">{rank['rank']}</div>
<div class="participant-info">
<div class="participant-name">{rank['name']}</div>
<div class="participant-count">发言数{rank['count']}</div>
<div class="participant-characteristics">
{characteristics}
</div>
<div class="participant-words">
{words}
</div>
</div>
</div>""")
html = html.replace('<!-- 在这里填充话唠榜数据 -->', '\n'.join(chatty))
# 处理熬夜冠军
nightOwl = json_data['sections']['analytics']['nightOwl']
f = f"""
<div class="night-owl-item">
<div class="owl-crown" title="熬夜冠军">👑</div>
<div class="owl-info">
<div class="owl-name">{nightOwl['name']}</div>
<div class="owl-title">{nightOwl['title']}</div>
<div class="owl-time">最晚活跃时间{nightOwl['latestTime']}</div>
<div class="owl-messages">深夜消息数{nightOwl['messageCount']}</div>
<div class="owl-last-message">{nightOwl['lastMessage']}</div>
<div class="owl-note">熬夜时段定义为23:00-06:00已考虑不同时区</div>
</div>"""
html = html.replace('<!-- 在这里填充熬夜冠军内容 -->','\n' + f + '\n')
# 处理词云
words = []
for word in json_data['sections']['wordCloud']['words']:
words.append(f"""
<span class="cloud-word" style="left: {word.get('x', 300)}px; top: {word.get('y', 120)}px;
font-size: {word['size']}px; color: {word['color']};
transform: rotate({word['rotation']}deg);">{word['text']}</span>""")
html = html.replace('<!-- 在这里填充词云内容 -->', '\n'.join(words))
# 处理词云的分类
types = []
for typ in json_data['sections']['wordCloud']['legend']:
types.append(f""" <div class="legend-item">
<span class="legend-color" style="background-color: {typ['color']};"></span>
<span class="legend-label">{typ['label']}</span>
</div>
"""
)
html = html.replace('<!-- 在这里填充词云分类内容 -->', '\n'.join(types))
# 处理页脚
footer = json_data['footer']
html = html.replace('[群名称]', footer['dataSource'])
html = html.replace('[当前时间]', footer['generationTime'])
html = html.replace('[日期] [时间范围]', footer['statisticalPeriod'])
return html
if __name__ == '__main__':
json_data = r"```json\n{\n\"header\": {\n\"title\": \"群聊报告\",\n\"date\": \"2025-04-29\",\n\"metaInfo\": {\n\"totalMessages\": \"30\",\n\"activeUsers\": \"12\",\n\"timeRange\": \"07:03:10 - 15:36:25\"\n}\n},\n\"sections\": {\n\"hotTopics\": {\n\"items\": [\n{\n\"name\": \"AI技术讨论\",\n\"category\": \"科技\",\n\"summary\": \"群内围绕AI技术进行了深入讨论包括Qwen3模型的开源、Vidu Q1的体验、夸克AI相机等话题。\",\n\"keywords\": [\"Qwen3\", \"Vidu Q1\", \"夸克AI相机\"],\n\"mentions\": \"10\"\n},\n{\n\"name\": \"熬夜与加班\",\n\"category\": \"生活\",\n\"summary\": \"群成员讨论了熬夜和加班的现象,尤其是科技行业的加班文化及其对身体的影响。\",\n\"keywords\": [\"熬夜\", \"加班\", \"卷王\"],\n\"mentions\": \"8\"\n}\n]\n},\n\"tutorials\": {\n\"items\": [\n{\n\"type\": \"TUTORIAL\",\n\"title\": \"Qwen3深夜正式开源\",\n\"sharedBy\": \"苍何\",\n\"time\": \"2025-04-29 09:20:23\",\n\"summary\": \"Qwen3小尺寸也能大力出奇迹欢迎来到这个荒诞又灿烂的时代。\",\n\"keyPoints\": [\"开源\", \"小尺寸\", \"高性能\"],\n\"url\": \"http://mp.weixin.qq.com/s?__biz=MzIyMzA5NjEyMA==&mid=2647670717&idx=1&sn=edec1f6cda0c1227e72cd07abf4228ff&chksm=f19a699bb993eb9ed2850ba329f382668bc7edc8a2d7d4a94de2d29c15cf87aa05bf6b48dc6d&mpshare=1&scene=1&srcid=0429TzXAJtS5jA2QI9hLEroV&sharer_shareinfo=7fd7493f3ccf9923f55b48a05619ce1b&sharer_shareinfo_first=fc872ba73c219b858d700a9db530b5b1#rd\",\n\"domain\": \"mp.weixin.qq.com\",\n\"category\": \"AI\"\n},\n{\n\"type\": \"TUTORIAL\",\n\"title\": \"体验完刚上线的Vidu Q1\",\n\"sharedBy\": \"苍何\",\n\"time\": \"2025-04-29 09:39:42\",\n\"summary\": \"AI视频清晰度一致性都上了一个台阶。\",\n\"keyPoints\": [\"Vidu Q1\", \"AI视频\", \"清晰度\"],\n\"url\": \"http://mp.weixin.qq.com/s?__biz=MzU4NTE1Mjg4MA==&mid=2247493267&idx=1&sn=0189fb501578ce8e27142fbe2f590d03&chksm=fc9a946728c367005c19cb5a335300d05d51a441f9f20424a0a72c904a47bdf003252576318a&mpshare=1&scene=1&srcid=04297l70B2zsuypDfjUh0rh5&sharer_shareinfo=181efb947f938ab90786c776bf7bbda7&sharer_shareinfo_first=181efb947f938ab90786c776bf7bbda7#rd\",\n\"domain\": \"mp.weixin.qq.com\",\n\"category\": \"AI\"\n},\n{\n\"type\": \"TUTORIAL\",\n\"title\": \"阿里新出的夸克AI相机\",\n\"sharedBy\": \"苍何\",\n\"time\": \"2025-04-29 09:42:38\",\n\"summary\": \"夸克AI相机超多新奇的玩法太抽象了。\",\n\"keyPoints\": [\"夸克AI相机\", \"新奇玩法\", \"抽象\"],\n\"url\": \"http://mp.weixin.qq.com/s?__biz=MzU4NTE1Mjg4MA==&mid=2247493275&idx=1&sn=93556ddd1da7fb8733a23a7c4adbb76b&chksm=fc2a2d25774cce23c75acd8850b85c585c0bcf78d14b810e157efaec5106abf563cf58e26aef&mpshare=1&scene=1&srcid=0429vDf8NbEzNLBQQyFlABmU&sharer_shareinfo=28b94477ec8201b88aa30338e82e8999&sharer_shareinfo_first=28b94477ec8201b88aa30338e82e8999#rd\",\n\"domain\": \"mp.weixin.qq.com\",\n\"category\": \"AI\"\n},\n{\n\"type\": \"TUTORIAL\",\n\"title\": \"仅2MBWindows瞬间超级丝滑\",\n\"sharedBy\": \"AHapi²⁰²⁵\",\n\"time\": \"2025-04-29 11:13:38\",\n\"summary\": \"这才是,真神器!\",\n\"keyPoints\": [\"Windows优化\", \"2MB\", \"神器\"],\n\"url\": \"https://mp.weixin.qq.com/s/es77Jc6Du03ppJD5XJeQUg\",\n\"domain\": \"mp.weixin.qq.com\",\n\"category\": \"工具\"\n}\n]\n},\n\"importantMessages\": {\n\"items\": [\n{\n\"time\": \"2025-04-29 10:00:18\",\n\"sender\": \"苍何\",\n\"type\": \"NEWS\",\n\"priority\": \"\",\n\"content\": \"2025年04月29日 AI科技早报\",\n\"fullContent\": \"1、阿里开源8款Qwen3模型集成MCP性能超DeepSeek-R1、OpenAI o1。\\\\n\\\\n2、Qafind Labs发布ChatDLM扩散语言模型推理速度高达2800 tokens/s。\\\\n\\\\n3、腾讯开源Kuikly跨端框架基于Kotlin支持多平台开发已应用于QQ。\\\\n\\\\n4、OpenAI 推出 ChatGPT 购物功能,用户可通过 ChatGPT 便捷购物。\\\\n\\\\n5、字节Seed团队提出PHD-Transformer突破预训练长度扩展瓶颈。\\\\n\\\\n6、百度发布文心快码3.5版本与多<EFBFBD>
with open('text.html', 'w', encoding='utf-8') as f:
f.write(main(json_data))