新增年度关键词

This commit is contained in:
SiYuan 2024-02-09 15:23:13 +08:00
parent 85cff9aaea
commit 163b2ef269
3 changed files with 123 additions and 12 deletions

View File

@ -3,6 +3,8 @@ from collections import Counter
import sys import sys
from datetime import datetime from datetime import datetime
import jieba
from app.DataBase import msg_db, MsgType from app.DataBase import msg_db, MsgType
from pyecharts import options as opts from pyecharts import options as opts
from pyecharts.charts import WordCloud, Calendar, Bar, Line, Pie from pyecharts.charts import WordCloud, Calendar, Bar, Line, Pie
@ -64,6 +66,46 @@ def wordcloud_(wxid, time_range=None):
} }
def get_wordcloud(text):
total_msg_len = len(text)
# 使用jieba进行分词并加入停用词
words = jieba.cut(text)
# 统计词频
word_count = Counter(words)
# 过滤停用词
stopwords_file = './app/data/stopwords.txt'
with open(stopwords_file, "r", encoding="utf-8") as stopword_file:
stopwords1 = set(stopword_file.read().splitlines())
# 构建 FFmpeg 可执行文件的路径
stopwords = set()
stopwords_file = './app/resources/data/stopwords.txt'
if not os.path.exists(stopwords_file):
resource_dir = getattr(sys, '_MEIPASS', os.path.abspath(os.path.dirname(__file__)))
stopwords_file = os.path.join(resource_dir, 'app', 'resources', 'data', 'stopwords.txt')
with open(stopwords_file, "r", encoding="utf-8") as stopword_file:
stopwords = set(stopword_file.read().splitlines())
stopwords = stopwords.union(stopwords1)
filtered_word_count = {word: count for word, count in word_count.items() if len(word) > 1 and word not in stopwords}
# 转换为词云数据格式
data = [(word, count) for word, count in filtered_word_count.items()]
# text_data = data
data.sort(key=lambda x: x[1], reverse=True)
text_data = data[:100] if len(data) > 100 else data
# 创建词云图
keyword, max_num = text_data[0]
w = (
WordCloud()
.add(series_name="聊天文字", data_pair=text_data, word_size_range=[5, 40])
)
return {
'chart_data_wordcloud': w.dump_options_with_quotes(),
'keyword': keyword,
'keyword_max_num': max_num,
}
def wordcloud_christmas(wxid, year='2023'): def wordcloud_christmas(wxid, year='2023'):
import jieba import jieba
txt_messages = msg_db.get_messages_by_type(wxid, MsgType.TEXT, year) txt_messages = msg_db.get_messages_by_type(wxid, MsgType.TEXT, year)
@ -375,6 +417,8 @@ def my_message_counter(time_range, my_name=''):
types_count = {} types_count = {}
send_num = 0 # 发送消息的数量 send_num = 0 # 发送消息的数量
weekday_count = {} weekday_count = {}
str_content = ''
total_text_num = 0
for message in msg_data: for message in msg_data:
type_ = message[2] type_ = message[2]
is_sender = message[4] is_sender = message[4]
@ -393,6 +437,10 @@ def my_message_counter(time_range, my_name=''):
weekday_count[weekday] += 1 weekday_count[weekday] += 1
else: else:
weekday_count[weekday] = 1 weekday_count[weekday] = 1
if type_ == 1:
total_text_num += len(message[7])
if is_sender == 1:
str_content += message[7]
receive_num = len(msg_data) - send_num receive_num = len(msg_data) - send_num
data = [[types_.get(key), value] for key, value in types_count.items() if key in types_] data = [[types_.get(key), value] for key, value in types_count.items() if key in types_]
if not data: if not data:
@ -428,9 +476,14 @@ def my_message_counter(time_range, my_name=''):
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%", position='inside')) .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%", position='inside'))
# .render("./data/聊天统计/pie_scroll_legend.html") # .render("./data/聊天统计/pie_scroll_legend.html")
) )
w = get_wordcloud(str_content)
return { return {
'chart_data_sender': p2.dump_options_with_quotes(), 'chart_data_sender': p2.dump_options_with_quotes(),
'chart_data_types': p1.dump_options_with_quotes(), 'chart_data_types': p1.dump_options_with_quotes(),
'chart_data_wordcloud': w.get('chart_data_wordcloud'),
'keyword': w.get('keyword'),
'keyword_max_num': w.get('keyword_max_num'),
'total_text_num':total_text_num,
} }

View File

@ -5,7 +5,7 @@ import traceback
import requests import requests
from PyQt5.QtCore import QThread, pyqtSignal, QSize, Qt from PyQt5.QtCore import QThread, pyqtSignal, QSize, Qt
from PyQt5.QtGui import QPixmap from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout, QApplication, QTextBrowser from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QHBoxLayout, QApplication, QTextBrowser, QMessageBox
from app.log import logger from app.log import logger
from app.ui.Icon import Icon from app.ui.Icon import Icon
@ -61,10 +61,14 @@ class AIChat(QWidget, Ui_Form):
self.init_ui() self.init_ui()
self.show_chats() self.show_chats()
self.pushButton.clicked.connect(self.send_msg) self.pushButton.clicked.connect(self.send_msg)
self.toolButton.clicked.connect(self.tool)
def init_ui(self): def init_ui(self):
self.textEdit.installEventFilter(self) self.textEdit.installEventFilter(self)
def tool(self):
QMessageBox.information(self, "温馨提示", "暂未接入聊天数据您可进行基础的AI对话后续更新敬请期待")
def chat(self, text): def chat(self, text):
self.now_message.append(text) self.now_message.append(text)
self.scrollArea.verticalScrollBar().setValue(self.scrollArea.verticalScrollBar().maximum()) self.scrollArea.verticalScrollBar().setValue(self.scrollArea.verticalScrollBar().maximum())

View File

@ -252,15 +252,48 @@ p {
} }
.chart{ .chart{
width: 800px; width: 800px;
height: 300px;
}
.chart-container{
display: flex;
}
#word_cloud{
width: 800px;
height: 800px;
}
@media screen and (max-width:480px){
.chart{
width: 300px;
height: 250px;
}
.chart-container{
display:flex;
flex-direction: column;
}
#word_cloud{
width: 400px;
height: 400px; height: 400px;
} }
}
@media screen and (max-width:600px){ #keywords {
.chart{ font-size: 2.5em;
width: 400px; color: #003366;
height: 220px; animation: slideIn 1.5s ease-out;
transform: skew(-15deg);
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateX(-50px) skew(-15deg);
}
to {
opacity: 1;
transform: translateX(0) skew(-15deg);
} }
} }
</style> </style>
</head> </head>
<body> <body>
@ -270,18 +303,25 @@ p {
<div class="section"> <div class="section">
<div id="cover"> <div id="cover">
<h1>年度聊天报告</h1> <h1>年度聊天报告</h1>
<p>统计、分析、回顾,记录聊天时光</p> <p>可掌控的才真正属于你</p>
<button id="enterButton" onclick="navigateToNextPage()">进入报告</button> <button id="enterButton" onclick="navigateToNextPage()">进入报告</button>
</div> </div>
</div> </div>
<div class="section cover"> <div class="section cover">
<h1>2023年</h1> <h1>2023年</h1>
<p>你一共给<span class="number">{{contact_num}}</span>个联系人<br>发送了<span class="number">{{send_msg_num}}</span>条消息<br>收到了<span class="number">{{receive_msg_num}}</span>条消息</p> <p>你一共给<span class="number">{{contact_num}}</span>个联系人<br>发送了<span class="number">{{send_msg_num}}</span>条消息<br>收到了<span class="number">{{receive_msg_num}}</span>条消息<br>总计<span class="number">{{total_text_num}}</span></p>
<div id="sender-chart" class="chart" ></div> <div class="chart-container">
<div id="types-chart" class="chart"></div> <div id="types-chart" class="chart"></div>
<div id="sender-chart" class="chart" ></div>
</div>
</div> </div>
<div class="section cover"> <div class="section cover">
<h1>我的年度好友</h1> <h1>年度关键词</h1>
<div id="keywords">“{{keyword}}”<span class="number">{{keyword_max_num}}</span></div>
<div id="word_cloud"></div>
</div>
<div class="section cover">
<h1>年度聊天好友</h1>
<h2>聊天榜单</h2> <h2>聊天榜单</h2>
<ul> <ul>
{% for contact,msg_num in contact_topN:%} {% for contact,msg_num in contact_topN:%}
@ -360,6 +400,20 @@ p {
document.getElementById('sender-chart'), 'white', {renderer: 'canvas'}); document.getElementById('sender-chart'), 'white', {renderer: 'canvas'});
var result = {{chart_data_sender|safe}}; var result = {{chart_data_sender|safe}};
chart_51ebd4312946429e9c32b2b55b96a4.setOption(result); chart_51ebd4312946429e9c32b2b55b96a4.setOption(result);
var chart_51ebd4312946429e9c32b2b55b96 = echarts.init(
document.getElementById('word_cloud'), 'white', {renderer: 'canvas'});
var result = {{chart_data_wordcloud|safe}};
// 获取屏幕宽度
const screenWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
// 根据屏幕宽度设置字体范围
let fontSizeRange;
if (screenWidth < 768) { // 手机屏幕
fontSizeRange = [5, 40];
} else { // 电脑屏幕
fontSizeRange = [10, 100];
}
result.series[0].sizeRange = fontSizeRange;
chart_51ebd4312946429e9c32b2b55b96.setOption(result);
</script> </script>
</body> </body>
</html> </html>