新增消息统计三个饼图

This commit is contained in:
shuaikangzhou 2024-01-29 23:48:15 +08:00
parent 61aca7d0e3
commit 85f505f8a0
5 changed files with 170 additions and 16 deletions

View File

@ -1,4 +0,0 @@
from .analysis import Analysis
__all__=['Analysis']

View File

@ -1,11 +1,13 @@
import os import os
from collections import Counter from collections import Counter
import sys import sys
from datetime import datetime
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 from pyecharts.charts import WordCloud, Calendar, Bar, Line, Pie
os.makedirs('./data/聊天统计/',exist_ok=True)
def wordcloud_(wxid, time_range=None): def wordcloud_(wxid, time_range=None):
import jieba import jieba
txt_messages = msg_db.get_messages_by_type(wxid, MsgType.TEXT, time_range=time_range) txt_messages = msg_db.get_messages_by_type(wxid, MsgType.TEXT, time_range=time_range)
@ -240,10 +242,131 @@ def hour_count(wxid, is_Annual_report=False, year='2023'):
} }
class Analysis: types = {
pass '文本': 1,
'图片': 3,
'语音': 34,
'视频': 43,
'表情包': 47,
'音乐与音频': 4903,
'文件': 4906,
'分享卡片': 4905,
'转账': 492000,
'音视频通话': 50,
'拍一拍等系统消息': 10000,
}
types_ = {
1: '文本',
3: '图片',
34: '语音',
43: '视频',
47: '表情包',
4957: '引用消息',
4903: '音乐与音频',
4906: '文件',
4905: '分享卡片',
492000: '转账',
50: '音视频通话',
10000: '拍一拍等系统消息',
}
def get_weekday(timestamp):
# 将时间戳转换为日期时间对象
dt_object = datetime.fromtimestamp(timestamp)
# 获取星期几0代表星期一1代表星期二以此类推
weekday = dt_object.weekday()
weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
return weekdays[weekday]
def sender(wxid, time_range, my_name='', ta_name=''):
msg_data = msg_db.get_messages(wxid, time_range)
types_count = {}
send_num = 0 # 发送消息的数量
weekday_count = {}
for message in msg_data:
type_ = message[2]
is_sender = message[4]
subType = message[3]
timestamp = message[5]
weekday = get_weekday(timestamp)
str_time = message[8]
send_num += is_sender
type_ = f'{type_}{subType:0>2d}' if subType != 0 else type_
type_ = int(type_)
if type_ in types_count:
types_count[type_] += 1
else:
types_count[type_] = 1
if weekday in weekday_count:
weekday_count[weekday] += 1
else:
weekday_count[weekday] = 1
receive_num = len(msg_data) - send_num
data = [[types_.get(key), value] for key, value in types_count.items() if key in types_]
if not data:
return {
'chart_data_sender': None,
'chart_data_types': None,
'chart_data_weekday': None,
}
p1 = (
Pie()
.add(
"",
data,
center=["40%", "50%"],
)
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(),
toolbox_opts=opts.ToolboxOpts(),
title_opts=opts.TitleOpts(title="消息类型占比"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%",pos_top="20%", orient="vertical"),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
# .render("./data/聊天统计/types_pie.html")
)
p2 = (
Pie()
.add(
"",
[[my_name, send_num], [ta_name, receive_num]],
center=["40%", "50%"],
)
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(),
toolbox_opts=opts.ToolboxOpts(),
title_opts=opts.TitleOpts(title="双方消息占比"),
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%",pos_top="20%", orient="vertical"),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%"))
# .render("./data/聊天统计/pie_scroll_legend.html")
)
p3 = (
Pie()
.add(
"",
[[key,value] for key,value in weekday_count.items()],
radius=["40%", "75%"],
)
.set_global_opts(
datazoom_opts=opts.DataZoomOpts(),
toolbox_opts=opts.ToolboxOpts(),
title_opts=opts.TitleOpts(title="星期分布图"),
legend_opts=opts.LegendOpts(orient="vertical", pos_top="15%", pos_left="2%"),
)
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%"))
# .render("./data/聊天统计/pie_weekdays.html")
)
return {
'chart_data_sender': p2.dump_options_with_quotes(),
'chart_data_types': p1.dump_options_with_quotes(),
'chart_data_weekday': p3.dump_options_with_quotes(),
}
if __name__ == '__main__': if __name__ == '__main__':
msg_db.init_database(path='../DataBase/Msg/MSG.db') msg_db.init_database(path='../DataBase/Msg/MSG.db')
# w = wordcloud('wxid_0o18ef858vnu22') # w = wordcloud('wxid_0o18ef858vnu22')
@ -253,5 +376,7 @@ if __name__ == '__main__':
wxid = 'wxid_0o18ef858vnu22' wxid = 'wxid_0o18ef858vnu22'
# data = month_count(wxid, time_range=None) # data = month_count(wxid, time_range=None)
# data['chart'].render("./data/聊天统计/month_count.html") # data['chart'].render("./data/聊天统计/month_count.html")
data = calendar_chart(wxid, time_range=None) # data = calendar_chart(wxid, time_range=None)
data['chart'].render("./data/聊天统计/calendar_chart.html") # data['chart'].render("./data/聊天统计/calendar_chart.html")
data = sender(wxid, time_range=None, my_name='发送', ta_name='接收')
print(data)

View File

@ -29,8 +29,16 @@
</div> </div>
</div> </div>
<div id="echarts-month_count" style="width: 800px; height: 600px;"></div> <div id="echarts-month_count" style="width: 800px; height: 600px;"></div>
<div>
<h2>消息统计</h2>
<div id="echarts-sender" style="width: 800px; height: 600px;"></div>
<div id="echarts-types" style="width: 800px; height: 600px;"></div>
<div id="echarts-weekday" style="width: 800px; height: 600px;"></div>
</div>
<div id="echarts-wordcloud" style="width: 800px; height: 800px;"></div> <div id="echarts-wordcloud" style="width: 800px; height: 800px;"></div>
<div id="echarts-calendar" style="width: 800px; height: 300px;"></div> <div id="echarts-calendar" style="width: 800px; height: 300px;"></div>
<script type="text/javascript"> function getRTime() { <script type="text/javascript"> function getRTime() {
var tt = document.getElementById("first_time").innerText; var tt = document.getElementById("first_time").innerText;
var EndTime = new Date(tt); var EndTime = new Date(tt);
@ -78,5 +86,21 @@ setInterval(getRTime, 1000);
myChart.setOption(JSON.parse(option)); myChart.setOption(JSON.parse(option));
}); });
</script> </script>
<script>
fetch('/message_counter')
.then(response => response.json())
.then(chartOptions => {
// 在这里使用 ECharts 渲染图表
var myChart = echarts.init(document.getElementById('echarts-sender'));
var option = chartOptions.chart_data_sender;
myChart.setOption(JSON.parse(option));
var myChart1 = echarts.init(document.getElementById('echarts-types'));
var option = chartOptions.chart_data_types;
myChart1.setOption(JSON.parse(option));
var myChart2 = echarts.init(document.getElementById('echarts-weekday'));
var option = chartOptions.chart_data_weekday;
myChart2.setOption(JSON.parse(option));
});
</script>
</body> </body>
</html> </html>

View File

@ -70,7 +70,7 @@ def christmas():
'chat_time': chat_time, 'chat_time': chat_time,
'chat_time_num': num, 'chat_time_num': num,
} }
month_data = msg_db.get_messages_by_month(contact.wxid,time_range=time_range) month_data = msg_db.get_messages_by_month(contact.wxid, time_range=time_range)
if month_data: if month_data:
month_data.sort(key=lambda x: x[1]) month_data.sort(key=lambda x: x[1])
@ -84,7 +84,7 @@ def christmas():
month_data = { month_data = {
'year': '2023', 'year': '2023',
'total_msg_num': msg_db.get_messages_number(contact.wxid,time_range=time_range), 'total_msg_num': msg_db.get_messages_number(contact.wxid, time_range=time_range),
'max_month': max_month, 'max_month': max_month,
'min_month': min_month, 'min_month': min_month,
'max_month_num': max_num, 'max_month_num': max_num,
@ -105,7 +105,6 @@ def christmas():
return html return html
@app.route('/upload') @app.route('/upload')
def upload(): def upload():
global html global html
@ -123,6 +122,7 @@ def upload():
response.headers.add('Content-Type', 'application/json') response.headers.add('Content-Type', 'application/json')
return response return response
def set_text(text): def set_text(text):
html = ''' html = '''
<!DOCTYPE html> <!DOCTYPE html>
@ -204,11 +204,10 @@ def get_chart_options():
return jsonify(data) return jsonify(data)
@app.route('/wordcloud') @app.route('/wordcloud')
def get_wordcloud(): def get_wordcloud():
time_range = (0, time.time()) time_range = (0, time.time())
print(time_range,contact.wxid) print(time_range, contact.wxid)
world_cloud_data = analysis.wordcloud_(contact.wxid, time_range=time_range) world_cloud_data = analysis.wordcloud_(contact.wxid, time_range=time_range)
return jsonify(world_cloud_data) return jsonify(world_cloud_data)
@ -228,10 +227,20 @@ def charts():
} }
return render_template('charts.html', **data) return render_template('charts.html', **data)
@app.route('/calendar') @app.route('/calendar')
def get_calendar(): def get_calendar():
time_range = (0, time.time()) time_range = (0, time.time())
world_cloud_data = analysis.calendar_chart(contact.wxid, time_range=time_range) world_cloud_data = analysis.calendar_chart(contact.wxid, time_range=time_range)
return jsonify(world_cloud_data) return jsonify(world_cloud_data)
@app.route('/message_counter')
def get_counter():
time_range = (0, time.time())
data = analysis.sender(contact.wxid, time_range=time_range, my_name=Me().name, ta_name=contact.remark)
return jsonify(data)
if __name__ == "__main__": if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0') app.run(debug=True, host='0.0.0.0')

View File

@ -162,7 +162,7 @@
> \[!IMPORTANT] > \[!IMPORTANT]
> >
> 声明:该项目有且仅有一个目的:“留痕”——我的数据我做主,前提是“我的数据”其次才是“我做主”,禁止任何人以任何形式将其用于任何非法用途,对于使用该程序所造成的任何后果,所有创作者不承担任何责任🙄<br> > 声明:该项目有且仅有一个目的:“留痕”——我的数据我做主,前提是“我的数据”其次才是“我做主”,禁止任何人以任何形式将其用于任何非法用途,对于使用该程序所造成的任何后果,所有创作者不承担任何责任🙄<br>
> 该软件不会对您使用的微信造成任何影响,更不会对他人的微信造成任何影响,不能找回删除的聊天记录,任何企图篡改微信聊天数据的想法都是无稽之谈。本项目所有功能均建立在”前言“的基础之上,基于该项目的所有开发者均不能接受任何有悖于”前言“的功能需求,违者后果自负。 > 该软件不能找回删除的聊天记录,任何企图篡改微信聊天数据的想法都是无稽之谈。本项目所有功能均建立在”前言“的基础之上,基于该项目的所有开发者均不能接受任何有悖于”前言“的功能需求,违者后果自负。
> <br>该软件不存在任何收费,谨防上当受骗 > <br>该软件不存在任何收费,谨防上当受骗
> <br>软件贩子勿扰,违规违法勿扰,二次开发请务必遵守开源协议 > <br>软件贩子勿扰,违规违法勿扰,二次开发请务必遵守开源协议