diff --git a/app/DataBase/msg.py b/app/DataBase/msg.py index c95e172..304f80c 100644 --- a/app/DataBase/msg.py +++ b/app/DataBase/msg.py @@ -222,10 +222,13 @@ class Msg: # result.sort(key=lambda x: x[5]) # return self.add_sender(result) - def get_messages_all(self): - sql = ''' + def get_messages_all(self,time_range=None): + 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 from MSG + {'WHERE CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''} order by CreateTime ''' if not self.open_flag: diff --git a/app/analysis/analysis.py b/app/analysis/analysis.py index 4564e55..b4cad9e 100644 --- a/app/analysis/analysis.py +++ b/app/analysis/analysis.py @@ -7,7 +7,9 @@ from app.DataBase import msg_db, MsgType from pyecharts import options as opts 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): import jieba 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(), toolbox_opts=opts.ToolboxOpts(), 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}")) # .render("./data/聊天统计/types_pie.html") @@ -340,7 +342,7 @@ def sender(wxid, time_range, my_name='', ta_name=''): 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"), + 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") @@ -349,7 +351,7 @@ def sender(wxid, time_range, my_name='', ta_name=''): Pie() .add( "", - [[key,value] for key,value in weekday_count.items()], + [[key, value] for key, value in weekday_count.items()], radius=["40%", "75%"], ) .set_global_opts( @@ -367,6 +369,71 @@ def sender(wxid, time_range, my_name='', ta_name=''): '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__': msg_db.init_database(path='../DataBase/Msg/MSG.db') # w = wordcloud('wxid_0o18ef858vnu22') diff --git a/app/ui/home/home_window.py b/app/ui/home/home_window.py index ff4b72f..0e7baa1 100644 --- a/app/ui/home/home_window.py +++ b/app/ui/home/home_window.py @@ -24,7 +24,7 @@ class HomeWindow(QWidget, Ui_Dialog): pass 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.start() QDesktopServices.openUrl(QUrl(f"http://127.0.0.1:21314/")) diff --git a/app/web_ui/templates/index.html b/app/web_ui/templates/index.html index 359a1d8..fc248d5 100644 --- a/app/web_ui/templates/index.html +++ b/app/web_ui/templates/index.html @@ -6,6 +6,8 @@ 微信年度聊天报告 + + @@ -23,7 +25,7 @@ } .section{ height: 100vh; - margin: 20px; + margin: 0px; display: flex; flex-direction: column; align-items: center; @@ -247,6 +249,17 @@ p { to { opacity: 1; } +} +.chart{ + width: 800px; + height: 400px; +} + +@media screen and (max-width:600px){ + .chart{ + width: 400px; + height: 220px; + } } @@ -256,11 +269,17 @@ p {
-

微信年度聊天报告

-

统计、分析、回顾,记录一年的聊天时光

+

年度聊天报告

+

统计、分析、回顾,记录聊天时光

+
+

2023年

+

你一共给{{contact_num}}个联系人
发送了{{send_msg_num}}条消息
收到了{{receive_msg_num}}条消息

+
+
+

我的年度好友

聊天榜单

@@ -332,5 +351,15 @@ p { fullpage_api.moveSectionDown(); } + diff --git a/app/web_ui/web.py b/app/web_ui/web.py index 3507454..a0a19fe 100644 --- a/app/web_ui/web.py +++ b/app/web_ui/web.py @@ -8,7 +8,7 @@ from pyecharts.charts import Bar from app.DataBase import msg_db, micro_msg_db 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 app = Flask(__name__) @@ -25,6 +25,8 @@ api_url = 'http://api.lc044.love/upload' def get_contact(wxid): contact_info_list = micro_msg_db.get_contact_by_username(wxid) + if not contact_info_list: + return ContactDefault('') contact_info = { 'UserName': contact_info_list[0], 'Alias': contact_info_list[1], @@ -40,16 +42,23 @@ def get_contact(wxid): @app.route("/") 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 = [] - 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_topN.append([contact,num]) + contact_topN.append([contact, num]) + my_message_counter_data = analysis.my_message_counter(time_range=time_range) data = { '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/")