统计信息新增日历图和逐月统计图

This commit is contained in:
shuaikangzhou 2024-01-27 17:32:23 +08:00
parent 9795ac9921
commit 8f16ef5e60
4 changed files with 148 additions and 142 deletions

View File

@ -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文件夹重试')

View File

@ -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")

View File

@ -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>

View File

@ -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')