mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-21 01:52:35 +08:00
新增消息统计
This commit is contained in:
parent
d8118c8433
commit
85cff9aaea
@ -222,10 +222,13 @@ class Msg:
|
|||||||
# result.sort(key=lambda x: x[5])
|
# result.sort(key=lambda x: x[5])
|
||||||
# return self.add_sender(result)
|
# return self.add_sender(result)
|
||||||
|
|
||||||
def get_messages_all(self):
|
def get_messages_all(self,time_range=None):
|
||||||
sql = '''
|
if time_range:
|
||||||
|
start_time, end_time = convert_to_timestamp(time_range)
|
||||||
|
sql = f'''
|
||||||
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,StrTalker,Reserved1,CompressContent
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,StrTalker,Reserved1,CompressContent
|
||||||
from MSG
|
from MSG
|
||||||
|
{'WHERE CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||||
order by CreateTime
|
order by CreateTime
|
||||||
'''
|
'''
|
||||||
if not self.open_flag:
|
if not self.open_flag:
|
||||||
|
@ -7,7 +7,9 @@ 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
|
||||||
|
|
||||||
os.makedirs('./data/聊天统计/',exist_ok=True)
|
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)
|
||||||
@ -324,7 +326,7 @@ def sender(wxid, time_range, my_name='', ta_name=''):
|
|||||||
datazoom_opts=opts.DataZoomOpts(),
|
datazoom_opts=opts.DataZoomOpts(),
|
||||||
toolbox_opts=opts.ToolboxOpts(),
|
toolbox_opts=opts.ToolboxOpts(),
|
||||||
title_opts=opts.TitleOpts(title="消息类型占比"),
|
title_opts=opts.TitleOpts(title="消息类型占比"),
|
||||||
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%",pos_top="20%", orient="vertical"),
|
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", pos_top="20%", orient="vertical"),
|
||||||
)
|
)
|
||||||
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
|
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
|
||||||
# .render("./data/聊天统计/types_pie.html")
|
# .render("./data/聊天统计/types_pie.html")
|
||||||
@ -340,7 +342,7 @@ def sender(wxid, time_range, my_name='', ta_name=''):
|
|||||||
datazoom_opts=opts.DataZoomOpts(),
|
datazoom_opts=opts.DataZoomOpts(),
|
||||||
toolbox_opts=opts.ToolboxOpts(),
|
toolbox_opts=opts.ToolboxOpts(),
|
||||||
title_opts=opts.TitleOpts(title="双方消息占比"),
|
title_opts=opts.TitleOpts(title="双方消息占比"),
|
||||||
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%",pos_top="20%", orient="vertical"),
|
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}%"))
|
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%"))
|
||||||
# .render("./data/聊天统计/pie_scroll_legend.html")
|
# .render("./data/聊天统计/pie_scroll_legend.html")
|
||||||
@ -349,7 +351,7 @@ def sender(wxid, time_range, my_name='', ta_name=''):
|
|||||||
Pie()
|
Pie()
|
||||||
.add(
|
.add(
|
||||||
"",
|
"",
|
||||||
[[key,value] for key,value in weekday_count.items()],
|
[[key, value] for key, value in weekday_count.items()],
|
||||||
radius=["40%", "75%"],
|
radius=["40%", "75%"],
|
||||||
)
|
)
|
||||||
.set_global_opts(
|
.set_global_opts(
|
||||||
@ -367,6 +369,71 @@ def sender(wxid, time_range, my_name='', ta_name=''):
|
|||||||
'chart_data_weekday': p3.dump_options_with_quotes(),
|
'chart_data_weekday': p3.dump_options_with_quotes(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def my_message_counter(time_range, my_name=''):
|
||||||
|
msg_data = msg_db.get_messages_all(time_range=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,
|
||||||
|
}
|
||||||
|
p1 = (
|
||||||
|
Pie()
|
||||||
|
.add(
|
||||||
|
"",
|
||||||
|
data,
|
||||||
|
center=["40%", "50%"],
|
||||||
|
)
|
||||||
|
.set_global_opts(
|
||||||
|
datazoom_opts=opts.DataZoomOpts(),
|
||||||
|
legend_opts=opts.LegendOpts(type_="scroll", pos_left="70%", pos_top="10%", orient="vertical"),
|
||||||
|
)
|
||||||
|
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}"))
|
||||||
|
# .render("./data/聊天统计/types_pie.html")
|
||||||
|
)
|
||||||
|
p2 = (
|
||||||
|
Pie()
|
||||||
|
.add(
|
||||||
|
"",
|
||||||
|
[['发送', send_num], ['接收',receive_num ]],
|
||||||
|
center=["40%", "50%"],
|
||||||
|
)
|
||||||
|
.set_global_opts(
|
||||||
|
datazoom_opts=opts.DataZoomOpts(),
|
||||||
|
legend_opts=opts.LegendOpts(type_="scroll", pos_left="70%", pos_top="20%", orient="vertical"),
|
||||||
|
)
|
||||||
|
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}\n{d}%", position='inside'))
|
||||||
|
# .render("./data/聊天统计/pie_scroll_legend.html")
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
'chart_data_sender': p2.dump_options_with_quotes(),
|
||||||
|
'chart_data_types': p1.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')
|
||||||
|
@ -24,7 +24,7 @@ class HomeWindow(QWidget, Ui_Dialog):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def report(self):
|
def report(self):
|
||||||
time_range = [0, time.time()]
|
time_range = ['2023-01-01 00:00:00', '2024-02-10 00:00:00']
|
||||||
self.report_thread = ReportThread(Me(), time_range)
|
self.report_thread = ReportThread(Me(), time_range)
|
||||||
self.report_thread.start()
|
self.report_thread.start()
|
||||||
QDesktopServices.openUrl(QUrl(f"http://127.0.0.1:21314/"))
|
QDesktopServices.openUrl(QUrl(f"http://127.0.0.1:21314/"))
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
<title>微信年度聊天报告</title>
|
<title>微信年度聊天报告</title>
|
||||||
<link rel="stylesheet" href="css/style.css">
|
<link rel="stylesheet" href="css/style.css">
|
||||||
<link rel="stylesheet" href="https://memotrace.lc044.love/static/css/fullpage.min.css" />
|
<link rel="stylesheet" href="https://memotrace.lc044.love/static/css/fullpage.min.css" />
|
||||||
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts@latest/dist/echarts.min.js"></script>
|
||||||
|
<script type="text/javascript" src="https://assets.pyecharts.org/assets/v5/echarts-wordcloud.min.js"></script>
|
||||||
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
|
||||||
<script type="text/javascript" src="https://memotrace.lc044.love/static/js/fullpage.min.js"></script>
|
<script type="text/javascript" src="https://memotrace.lc044.love/static/js/fullpage.min.js"></script>
|
||||||
<script type="text/javascript" src="https://davidshimjs.github.io/qrcodejs/qrcode.min.js"></script>
|
<script type="text/javascript" src="https://davidshimjs.github.io/qrcodejs/qrcode.min.js"></script>
|
||||||
@ -23,7 +25,7 @@
|
|||||||
}
|
}
|
||||||
.section{
|
.section{
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
margin: 20px;
|
margin: 0px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -247,6 +249,17 @@ p {
|
|||||||
to {
|
to {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.chart{
|
||||||
|
width: 800px;
|
||||||
|
height: 400px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width:600px){
|
||||||
|
.chart{
|
||||||
|
width: 400px;
|
||||||
|
height: 220px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@ -256,11 +269,17 @@ p {
|
|||||||
<div id="fullpage">
|
<div id="fullpage">
|
||||||
<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">
|
||||||
|
<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>
|
||||||
|
<div id="sender-chart" class="chart" ></div>
|
||||||
|
<div id="types-chart" class="chart"></div>
|
||||||
|
</div>
|
||||||
<div class="section cover">
|
<div class="section cover">
|
||||||
<h1>我的年度好友</h1>
|
<h1>我的年度好友</h1>
|
||||||
<h2>聊天榜单</h2>
|
<h2>聊天榜单</h2>
|
||||||
@ -332,5 +351,15 @@ p {
|
|||||||
fullpage_api.moveSectionDown();
|
fullpage_api.moveSectionDown();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
<script>
|
||||||
|
var chart_51ebd4312946429e9c32b2b55b96a479 = echarts.init(
|
||||||
|
document.getElementById('types-chart'), 'white', {renderer: 'canvas'});
|
||||||
|
var result = {{chart_data_types|safe}};
|
||||||
|
chart_51ebd4312946429e9c32b2b55b96a479.setOption(result);
|
||||||
|
var chart_51ebd4312946429e9c32b2b55b96a4 = echarts.init(
|
||||||
|
document.getElementById('sender-chart'), 'white', {renderer: 'canvas'});
|
||||||
|
var result = {{chart_data_sender|safe}};
|
||||||
|
chart_51ebd4312946429e9c32b2b55b96a4.setOption(result);
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -8,7 +8,7 @@ from pyecharts.charts import Bar
|
|||||||
|
|
||||||
from app.DataBase import msg_db, micro_msg_db
|
from app.DataBase import msg_db, micro_msg_db
|
||||||
from app.analysis import analysis
|
from app.analysis import analysis
|
||||||
from app.person import Contact, Me
|
from app.person import Contact, Me, ContactDefault
|
||||||
from app.util.emoji import get_most_emoji
|
from app.util.emoji import get_most_emoji
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
@ -25,6 +25,8 @@ api_url = 'http://api.lc044.love/upload'
|
|||||||
|
|
||||||
def get_contact(wxid):
|
def get_contact(wxid):
|
||||||
contact_info_list = micro_msg_db.get_contact_by_username(wxid)
|
contact_info_list = micro_msg_db.get_contact_by_username(wxid)
|
||||||
|
if not contact_info_list:
|
||||||
|
return ContactDefault('')
|
||||||
contact_info = {
|
contact_info = {
|
||||||
'UserName': contact_info_list[0],
|
'UserName': contact_info_list[0],
|
||||||
'Alias': contact_info_list[1],
|
'Alias': contact_info_list[1],
|
||||||
@ -40,16 +42,23 @@ def get_contact(wxid):
|
|||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def index():
|
def index():
|
||||||
contact_topN_num = msg_db.get_chatted_top_contacts(time_range=time_range, top_n=6)
|
contact_topN_num = msg_db.get_chatted_top_contacts(time_range=time_range, top_n=9999999,contain_chatroom=True)
|
||||||
|
total_msg_num = sum(list(map(lambda x:x[1],contact_topN_num)))
|
||||||
contact_topN = []
|
contact_topN = []
|
||||||
for wxid,num in contact_topN_num:
|
send_msg_num = msg_db.get_send_messages_number_sum(time_range)
|
||||||
|
contact_topN_num = msg_db.get_chatted_top_contacts(time_range=time_range, top_n=9999999, contain_chatroom=False)
|
||||||
|
for wxid, num in contact_topN_num[:6]:
|
||||||
contact = get_contact(wxid)
|
contact = get_contact(wxid)
|
||||||
contact_topN.append([contact,num])
|
contact_topN.append([contact, num])
|
||||||
|
my_message_counter_data = analysis.my_message_counter(time_range=time_range)
|
||||||
data = {
|
data = {
|
||||||
'avatar': Me().smallHeadImgUrl,
|
'avatar': Me().smallHeadImgUrl,
|
||||||
'contact_topN':contact_topN,
|
'contact_topN': contact_topN,
|
||||||
|
'contact_num':len(contact_topN_num),
|
||||||
|
'send_msg_num':send_msg_num ,
|
||||||
|
'receive_msg_num':total_msg_num-send_msg_num,
|
||||||
}
|
}
|
||||||
return render_template('index.html', **data)
|
return render_template('index.html', **data,**my_message_counter_data)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/christmas/<wxid>")
|
@app.route("/christmas/<wxid>")
|
||||||
|
Loading…
Reference in New Issue
Block a user