mirror of
https://github.com/LC044/WeChatMsg
synced 2024-11-12 20:21:21 +08:00
统计信息新增日历图和逐月统计图
This commit is contained in:
parent
9795ac9921
commit
8f16ef5e60
@ -379,77 +379,57 @@ class Msg:
|
||||
lock.release()
|
||||
return [date[0] for date in result]
|
||||
|
||||
def get_messages_by_days(self, username_, is_Annual_report_=False, year_='2023'):
|
||||
if is_Annual_report_:
|
||||
sql = '''
|
||||
SELECT strftime('%Y-%m-%d',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ? AND strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
else:
|
||||
sql = '''
|
||||
SELECT strftime('%Y-%m-%d',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ?
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
def get_messages_by_days(self, username_, time_range=None):
|
||||
result = None
|
||||
if not self.open_flag:
|
||||
return None
|
||||
if time_range:
|
||||
start_time, end_time = time_range
|
||||
sql = f'''
|
||||
SELECT strftime('%Y-%m-%d',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ?
|
||||
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
result = None
|
||||
if not self.open_flag:
|
||||
return None
|
||||
try:
|
||||
lock.acquire(True)
|
||||
if is_Annual_report_:
|
||||
self.cursor.execute(sql, [username_, year_])
|
||||
else:
|
||||
self.cursor.execute(sql, [username_])
|
||||
self.cursor.execute(sql, [username_])
|
||||
result = self.cursor.fetchall()
|
||||
finally:
|
||||
lock.release()
|
||||
return result
|
||||
|
||||
def get_messages_by_month(self, username_, is_Annual_report_=False, year_='2023'):
|
||||
if is_Annual_report_:
|
||||
sql = '''
|
||||
SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ? AND strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
else:
|
||||
sql = '''
|
||||
SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ?
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
def get_messages_by_month(self, username_, time_range=None):
|
||||
result = None
|
||||
if not self.open_flag:
|
||||
return None
|
||||
if time_range:
|
||||
start_time, end_time = time_range
|
||||
sql = f'''
|
||||
SELECT strftime('%Y-%m',CreateTime,'unixepoch','localtime') as days,count(MsgSvrID)
|
||||
from (
|
||||
SELECT MsgSvrID, CreateTime
|
||||
FROM MSG
|
||||
WHERE StrTalker = ?
|
||||
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||
)
|
||||
group by days
|
||||
'''
|
||||
try:
|
||||
lock.acquire(True)
|
||||
if is_Annual_report_:
|
||||
self.cursor.execute(sql, [username_, year_])
|
||||
else:
|
||||
self.cursor.execute(sql, [username_])
|
||||
self.cursor.execute(sql, [username_])
|
||||
result = self.cursor.fetchall()
|
||||
except sqlite3.DatabaseError:
|
||||
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||
finally:
|
||||
lock.release()
|
||||
# result.sort(key=lambda x: x[5])
|
||||
return result
|
||||
|
||||
def get_messages_by_hour(self, username_, year_='all'):
|
||||
@ -572,12 +552,14 @@ class Msg:
|
||||
lock.release()
|
||||
return result
|
||||
|
||||
def get_messages_number(self, username_, year_="all") -> int:
|
||||
def get_messages_number(self, username_, time_range=None) -> int:
|
||||
if time_range:
|
||||
start_time, end_time = time_range
|
||||
sql = f"""
|
||||
SELECT Count(MsgSvrID)
|
||||
from MSG
|
||||
where StrTalker = ?
|
||||
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||
{'AND CreateTime>' + str(start_time) + ' AND CreateTime<' + str(end_time) if time_range else ''}
|
||||
group by type, subtype
|
||||
order by Count(MsgSvrID) desc
|
||||
"""
|
||||
@ -586,7 +568,7 @@ class Msg:
|
||||
return None
|
||||
try:
|
||||
lock.acquire(True)
|
||||
self.cursor.execute(sql, [username_, year_] if year_ != "all" else [username_])
|
||||
self.cursor.execute(sql, [username_])
|
||||
result = self.cursor.fetchone()
|
||||
except sqlite3.DatabaseError:
|
||||
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||
|
@ -73,7 +73,7 @@ def wordcloud(wxid, is_Annual_report=False, year='2023', who='1'):
|
||||
}
|
||||
|
||||
|
||||
def wordcloud_(wxid, is_Annual_report=False, time_range=None):
|
||||
def wordcloud_(wxid, time_range=None):
|
||||
import jieba
|
||||
txt_messages = msg_db.get_messages_by_type(wxid, MsgType.TEXT, time_range=time_range)
|
||||
if not txt_messages:
|
||||
@ -183,30 +183,15 @@ def wordcloud_christmas(wxid, year='2023'):
|
||||
}
|
||||
|
||||
|
||||
def calendar_chart(wxid, is_Annual_report=False, year='2023'):
|
||||
try:
|
||||
calendar_data = msg_db.get_messages_by_days(wxid, is_Annual_report, year)
|
||||
except:
|
||||
return {
|
||||
'calendar_chart_data': None,
|
||||
'chat_days': 0,
|
||||
}
|
||||
if not calendar_data:
|
||||
return {
|
||||
'calendar_chart_data': None,
|
||||
'chat_days': 0,
|
||||
}
|
||||
def calendar_chart(wxid, time_range=None):
|
||||
calendar_data = msg_db.get_messages_by_days(wxid,time_range)
|
||||
min_ = min(map(lambda x: x[1], calendar_data))
|
||||
max_ = max(map(lambda x: x[1], calendar_data))
|
||||
start_date_ = calendar_data[0][0]
|
||||
end_date_ = calendar_data[-1][0]
|
||||
print(start_date_, '---->', end_date_)
|
||||
if is_Annual_report:
|
||||
calendar_days = year
|
||||
calendar_title = f'{year}年聊天情况'
|
||||
else:
|
||||
calendar_days = (start_date_, end_date_)
|
||||
calendar_title = '和Ta的聊天情况'
|
||||
calendar_days = (start_date_, end_date_)
|
||||
calendar_title = '和Ta的聊天情况'
|
||||
c = (
|
||||
Calendar()
|
||||
.add(
|
||||
@ -226,43 +211,50 @@ def calendar_chart(wxid, is_Annual_report=False, year='2023'):
|
||||
)
|
||||
)
|
||||
return {
|
||||
'calendar_chart_data': c.dump_options_with_quotes(),
|
||||
'chart_data': c.dump_options_with_quotes(),
|
||||
'chat_days': len(calendar_data),
|
||||
# 'chart':c,
|
||||
}
|
||||
|
||||
|
||||
def month_count(wxid, is_Annual_report=False, year='2023'):
|
||||
def month_count(wxid, time_range=None):
|
||||
"""
|
||||
每月聊天条数
|
||||
"""
|
||||
msg_data = msg_db.get_messages_by_month(wxid, is_Annual_report, year)
|
||||
msg_data = msg_db.get_messages_by_month(wxid, time_range)
|
||||
y_data = list(map(lambda x: x[1], msg_data))
|
||||
x_axis = list(map(lambda x: x[0], msg_data))
|
||||
m = (
|
||||
Bar(init_opts=opts.InitOpts(width=f"{charts_width}px", height=f"{charts_height}px"))
|
||||
Bar(init_opts=opts.InitOpts())
|
||||
.add_xaxis(x_axis)
|
||||
.add_yaxis("消息数量", y_data,
|
||||
label_opts=opts.LabelOpts(is_show=False),
|
||||
itemstyle_opts=opts.ItemStyleOpts(color="skyblue"),
|
||||
label_opts=opts.LabelOpts(is_show=True),
|
||||
itemstyle_opts=opts.ItemStyleOpts(color="#ffae80"),
|
||||
)
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(title="逐月统计", subtitle=None),
|
||||
datazoom_opts=opts.DataZoomOpts(),
|
||||
toolbox_opts=opts.ToolboxOpts(),
|
||||
yaxis_opts=opts.AxisOpts(
|
||||
name="消息数",
|
||||
type_="value",
|
||||
axistick_opts=opts.AxisTickOpts(is_show=True),
|
||||
splitline_opts=opts.SplitLineOpts(is_show=True),
|
||||
),
|
||||
visualmap_opts=opts.VisualMapOpts(
|
||||
min_=min(y_data),
|
||||
max_=max(y_data),
|
||||
dimension=1, # 根据第2个维度(y 轴)进行映射
|
||||
is_piecewise=False, # 是否分段显示
|
||||
range_color=["#66ccff", "#003366"], # 设置颜色范围
|
||||
range_color=["#ffbe7a", "#fa7f6f"], # 设置颜色范围
|
||||
type_="color",
|
||||
pos_right="0%",
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
return {
|
||||
'chart_data': m
|
||||
'chart_data': m.dump_options_with_quotes(),
|
||||
# 'chart': m,
|
||||
}
|
||||
|
||||
|
||||
@ -314,13 +306,11 @@ class Analysis:
|
||||
if __name__ == '__main__':
|
||||
msg_db.init_database(path='../DataBase/Msg/MSG.db')
|
||||
# w = wordcloud('wxid_0o18ef858vnu22')
|
||||
w_data = wordcloud('wxid_27hqbq7vx5hf22', True, '2023')
|
||||
# print(w_data)
|
||||
# w['chart_data'].render("./data/聊天统计/wordcloud.html")
|
||||
c = calendar_chart('wxid_27hqbq7vx5hf22', False, '2023')
|
||||
c['chart_data'].render("./data/聊天统计/calendar.html")
|
||||
# print('c:::', c)
|
||||
m = month_count('wxid_27hqbq7vx5hf22', False, '2023')
|
||||
m['chart_data'].render("./data/聊天统计/month_num.html")
|
||||
h = hour_count('wxid_27hqbq7vx5hf22')
|
||||
h['chart_data'].render("./data/聊天统计/hour_count.html")
|
||||
# w_data = wordcloud('wxid_27hqbq7vx5hf22', True, '2023')
|
||||
# # print(w_data)
|
||||
# w_data['chart_data'].render("./data/聊天统计/wordcloud.html")
|
||||
wxid = 'wxid_0o18ef858vnu22'
|
||||
# data = month_count(wxid, time_range=None)
|
||||
# data['chart'].render("./data/聊天统计/month_count.html")
|
||||
data = calendar_chart(wxid, time_range=None)
|
||||
data['chart'].render("./data/聊天统计/calendar_chart.html")
|
||||
|
@ -6,24 +6,59 @@
|
||||
<title>微信年度聊天报告</title>
|
||||
<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>
|
||||
<style>
|
||||
body{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>{{my_nickname}}——{{ta_nickname}}</h1>
|
||||
<div id="echarts-container" style="width: 600px; height: 400px;"></div>
|
||||
<div>
|
||||
<p class="mt-3">我们第一次聊天在</p>
|
||||
<p id="first_time" class="first-time">{{first_time}}</p>
|
||||
<p class="mt-3">距今已有</p>
|
||||
<div class="mt-3">
|
||||
<span id="t_d"></span>
|
||||
<span id="t_h"></span>
|
||||
<span id="t_m"></span>
|
||||
<span id="t_s"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div id="echarts-month_count" style="width: 800px; height: 600px;"></div>
|
||||
<div id="echarts-wordcloud" style="width: 800px; height: 800px;"></div>
|
||||
<div id="echarts-calendar" style="width: 800px; height: 300px;"></div>
|
||||
<script type="text/javascript"> function getRTime() {
|
||||
var tt = document.getElementById("first_time").innerText;
|
||||
var EndTime = new Date(tt);
|
||||
var NowTime = new Date();
|
||||
var t = NowTime.getTime()-EndTime.getTime();
|
||||
var d = Math.floor(t / 1000 / 60 / 60 / 24);
|
||||
var h = Math.floor(t / 1000 / 60 / 60 % 24);
|
||||
var m = Math.floor(t / 1000 / 60 % 60);
|
||||
var s = Math.floor(t / 1000 % 60);
|
||||
document.getElementById("t_d").innerHTML = d + " 天";
|
||||
document.getElementById("t_h").innerHTML = h + " 时";
|
||||
document.getElementById("t_m").innerHTML = m + " 分";
|
||||
document.getElementById("t_s").innerHTML = s + " 秒";
|
||||
}
|
||||
setInterval(getRTime, 1000);
|
||||
|
||||
</script>
|
||||
<script>
|
||||
// 使用 AJAX 请求获取 Pyecharts 生成的图表配置项数据
|
||||
fetch('/get_chart_options')
|
||||
fetch('/month_count')
|
||||
.then(response => response.json())
|
||||
.then(chartOptions => {
|
||||
// 在这里使用 ECharts 渲染图表
|
||||
var myChart = echarts.init(document.getElementById('echarts-container'));
|
||||
var myChart = echarts.init(document.getElementById('echarts-month_count'));
|
||||
var option = chartOptions.chart_data;
|
||||
myChart.setOption(JSON.parse(option));
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// 使用 AJAX 请求获取 Pyecharts 生成的图表配置项数据
|
||||
fetch('/wordcloud')
|
||||
.then(response => response.json())
|
||||
.then(chartOptions => {
|
||||
@ -33,5 +68,15 @@
|
||||
myChart.setOption(JSON.parse(option));
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
fetch('/calendar')
|
||||
.then(response => response.json())
|
||||
.then(chartOptions => {
|
||||
// 在这里使用 ECharts 渲染图表
|
||||
var myChart = echarts.init(document.getElementById('echarts-calendar'));
|
||||
var option = chartOptions.chart_data;
|
||||
myChart.setOption(JSON.parse(option));
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -28,6 +28,13 @@ def index():
|
||||
|
||||
@app.route("/christmas")
|
||||
def christmas():
|
||||
t = '2023-1-01 00:00:00'
|
||||
s_t = time.strptime(t, "%Y-%m-%d %H:%M:%S") # 返回元祖
|
||||
start_time = int(time.mktime(s_t))
|
||||
t = '2023-12-31 23:59:59'
|
||||
s_t = time.strptime(t, "%Y-%m-%d %H:%M:%S") # 返回元祖
|
||||
end_time = int(time.mktime(s_t))
|
||||
time_range = (start_time, end_time)
|
||||
# 渲染模板,并传递图表的 HTML 到模板中
|
||||
try:
|
||||
first_message, first_time = msg_db.get_first_time_of_message(contact.wxid)
|
||||
@ -63,7 +70,7 @@ def christmas():
|
||||
'chat_time': chat_time,
|
||||
'chat_time_num': num,
|
||||
}
|
||||
month_data = msg_db.get_messages_by_month(contact.wxid, True, year_='2023')
|
||||
month_data = msg_db.get_messages_by_month(contact.wxid,time_range=time_range)
|
||||
|
||||
if month_data:
|
||||
month_data.sort(key=lambda x: x[1])
|
||||
@ -74,16 +81,18 @@ def christmas():
|
||||
else:
|
||||
max_month, max_num = '月份', 0
|
||||
min_month, min_num = '月份', 0
|
||||
|
||||
month_data = {
|
||||
'year': '2023',
|
||||
'total_msg_num': msg_db.get_messages_number(contact.wxid, '2023'),
|
||||
'total_msg_num': msg_db.get_messages_number(contact.wxid,time_range=time_range),
|
||||
'max_month': max_month,
|
||||
'min_month': min_month,
|
||||
'max_month_num': max_num,
|
||||
'min_month_num': min_num,
|
||||
}
|
||||
calendar_data = analysis.calendar_chart(contact.wxid, True, year='2023')
|
||||
emoji_msgs = msg_db.get_messages_by_type(contact.wxid, 47, year_='2023')
|
||||
|
||||
calendar_data = analysis.calendar_chart(contact.wxid, time_range)
|
||||
emoji_msgs = msg_db.get_messages_by_type(contact.wxid, 47, time_range=time_range)
|
||||
url, num = get_most_emoji(emoji_msgs)
|
||||
emoji_data = {
|
||||
'emoji_total_num': len(emoji_msgs),
|
||||
@ -96,21 +105,6 @@ def christmas():
|
||||
return html
|
||||
|
||||
|
||||
@app.route('/home')
|
||||
def home():
|
||||
try:
|
||||
first_message, first_time = msg_db.get_first_time_of_message(contact.wxid)
|
||||
except TypeError:
|
||||
return set_text('咱就是说,一次都没聊过就别分析了')
|
||||
data = {
|
||||
'sub_title': '二零二三年度报告',
|
||||
'avatar_path': contact.avatar_path,
|
||||
'nickname': contact.remark,
|
||||
'first_time': first_time,
|
||||
}
|
||||
|
||||
return render_template('home.html', **data)
|
||||
|
||||
|
||||
@app.route('/upload')
|
||||
def upload():
|
||||
@ -129,20 +123,6 @@ def upload():
|
||||
response.headers.add('Content-Type', 'application/json')
|
||||
return response
|
||||
|
||||
|
||||
@app.route('/wordcloud/<who>/')
|
||||
def one(who):
|
||||
wxid = contact.wxid
|
||||
# wxid = 'wxid_lltzaezg38so22'
|
||||
# print('wxid:'+wxid)
|
||||
world_cloud_data = analysis.wordcloud(wxid, who=who) # 获取与Ta的对话数据
|
||||
# print(world_cloud_data)
|
||||
who = "你" if who == '1' else "TA"
|
||||
with open('wordcloud.html', 'w', encoding='utf-8') as f:
|
||||
f.write(render_template('wordcloud.html', **world_cloud_data))
|
||||
return render_template('wordcloud.html', **world_cloud_data, who=who)
|
||||
|
||||
|
||||
def set_text(text):
|
||||
html = '''
|
||||
<!DOCTYPE html>
|
||||
@ -217,32 +197,41 @@ def generate_chart():
|
||||
return bar.dump_options_with_quotes()
|
||||
|
||||
|
||||
@app.route('/get_chart_options')
|
||||
@app.route('/month_count')
|
||||
def get_chart_options():
|
||||
chart_options = generate_chart()
|
||||
data = {
|
||||
'chart_data': chart_options
|
||||
}
|
||||
time_range = (0, time.time())
|
||||
data = analysis.month_count(contact.wxid, time_range=time_range)
|
||||
return jsonify(data)
|
||||
|
||||
|
||||
|
||||
@app.route('/wordcloud')
|
||||
def get_wordcloud():
|
||||
|
||||
time_range = (0, time.time())
|
||||
print(time_range)
|
||||
print(time_range,contact.wxid)
|
||||
|
||||
world_cloud_data = analysis.wordcloud_(contact.wxid, time_range=time_range)
|
||||
return jsonify(world_cloud_data)
|
||||
|
||||
|
||||
@app.route('/charts')
|
||||
def charts():
|
||||
# 渲染模板,并传递图表的 HTML 到模板中
|
||||
try:
|
||||
first_message, first_time = msg_db.get_first_time_of_message(contact.wxid)
|
||||
except TypeError:
|
||||
first_time = '2023-01-01 00:00:00'
|
||||
data = {
|
||||
'my_nickname':Me().name,
|
||||
'ta_nickname':contact.remark,
|
||||
'my_nickname': Me().name,
|
||||
'ta_nickname': contact.remark,
|
||||
'first_time': first_time
|
||||
}
|
||||
return render_template('charts.html',**data)
|
||||
|
||||
return render_template('charts.html', **data)
|
||||
|
||||
@app.route('/calendar')
|
||||
def get_calendar():
|
||||
time_range = (0, time.time())
|
||||
world_cloud_data = analysis.calendar_chart(contact.wxid, time_range=time_range)
|
||||
return jsonify(world_cloud_data)
|
||||
if __name__ == "__main__":
|
||||
app.run(debug=True, host='0.0.0.0')
|
||||
|
Loading…
Reference in New Issue
Block a user