mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-21 01:52:35 +08:00
聊天统计
This commit is contained in:
parent
3cf9d5b475
commit
d848a80b32
136
app/Ui/contact/analysis/analysis.py
Normal file
136
app/Ui/contact/analysis/analysis.py
Normal file
@ -0,0 +1,136 @@
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
from PyQt5.QtGui import *
|
||||
from app.DataBase import data
|
||||
|
||||
# class AnalysisController(QMainWindow, Ui_Dialog):
|
||||
# exitSignal = pyqtSignal()
|
||||
#
|
||||
# # username = ''
|
||||
# def __init__(self, username, parent=None):
|
||||
# super(AnalysisController, self).__init__(parent)
|
||||
# self.setupUi(self)
|
||||
# self.setWindowTitle('WeChat')
|
||||
# self.setWindowIcon(QIcon('./app/data/icon.png'))
|
||||
# self.Me = data.get_myinfo()
|
||||
import sys
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QSplitter, QApplication)
|
||||
from PyQt5.QtCore import (Qt, QUrl)
|
||||
from PyQt5.QtWebEngineWidgets import *
|
||||
from . import charts
|
||||
|
||||
|
||||
class AnalysisController(QWidget):
|
||||
def __init__(self, username):
|
||||
super().__init__()
|
||||
self.ta_username = username
|
||||
self.load_data()
|
||||
self.initUI()
|
||||
self.setWindowTitle('WeChat')
|
||||
self.setWindowIcon(QIcon('./app/data/icon.png'))
|
||||
# self.setBackground()
|
||||
|
||||
def load_data(self):
|
||||
charts.send_recv_rate(self.ta_username)
|
||||
charts.message_word_cloud(self.ta_username)
|
||||
charts.msg_type_rate(self.ta_username)
|
||||
charts.calendar_chart(self.ta_username)
|
||||
charts.month_num(self.ta_username)
|
||||
|
||||
def initUI(self):
|
||||
main_box = QHBoxLayout(self)
|
||||
self.browser1 = QWebEngineView()
|
||||
self.browser1.load(QUrl('http://www.baidu.com'))
|
||||
# self.browser1 = QFrame(self)
|
||||
# self.browser1.setFrameShape(QFrame.StyledPanel)
|
||||
# self.layoutWidget = QtWidgets.QWidget(self.browser1)
|
||||
# # self.layoutWidget.setGeometry(QtCore.QRect(71, 63, 227, 155))
|
||||
# self.verticalLayout = QtWidgets.QVBoxLayout(self.layoutWidget)
|
||||
# self.verticalLayout.setContentsMargins(0, 0, 0, 0)
|
||||
# self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
|
||||
# self.label_2 = QtWidgets.QLabel(self.layoutWidget)
|
||||
# _translate = QtCore.QCoreApplication.translate
|
||||
# conRemark = data.get_conRemark(self.ta_username)
|
||||
# self.label_2.setText(_translate("Dialog", f"{conRemark}"))
|
||||
# self.horizontalLayout_2.addWidget(self.label_2)
|
||||
# self.browser1.setLayout(self.horizontalLayout_2)
|
||||
|
||||
self.browser2 = QWebEngineView()
|
||||
self.browser2.load(QUrl('file:///data/聊天统计/wordcloud.html'))
|
||||
self.browser3 = QWebEngineView()
|
||||
self.browser3.load(QUrl('http://www.baidu.com'))
|
||||
self.browser4 = QWebEngineView()
|
||||
self.browser4.load(QUrl('http://www.baidu.com'))
|
||||
self.browser5 = QWebEngineView()
|
||||
self.browser5.load(QUrl('http://www.baidu.com'))
|
||||
self.browser6 = QWebEngineView()
|
||||
self.browser6.load(QUrl('http://www.baidu.com'))
|
||||
self.browser7 = QWebEngineView()
|
||||
self.browser7.load(QUrl('file:///data/聊天统计/month_num.html'))
|
||||
self.browser8 = QWebEngineView()
|
||||
self.browser8.load(QUrl('file:///data/聊天统计/calendar.html'))
|
||||
self.browser9 = QWebEngineView()
|
||||
self.browser9.load(QUrl('file:///data/聊天统计/msg_type_rate.html'))
|
||||
self.browser10 = QWebEngineView()
|
||||
self.browser10.load(QUrl('file:///data/聊天统计/send_recv_rate.html'))
|
||||
|
||||
splitter1 = QSplitter(Qt.Vertical)
|
||||
splitter2 = QSplitter(Qt.Horizontal)
|
||||
splitter3 = QSplitter(Qt.Horizontal)
|
||||
splitter4 = QSplitter(Qt.Vertical)
|
||||
splitter5 = QSplitter(Qt.Horizontal)
|
||||
splitter6 = QSplitter(Qt.Vertical)
|
||||
splitter7 = QSplitter(Qt.Vertical)
|
||||
splitter8 = QSplitter(Qt.Vertical)
|
||||
splitter9 = QSplitter(Qt.Vertical)
|
||||
|
||||
splitter1.addWidget(self.browser1)
|
||||
splitter1.addWidget(splitter2)
|
||||
splitter1.setSizes([1, 5])
|
||||
|
||||
splitter2.addWidget(splitter6)
|
||||
splitter2.addWidget(splitter3)
|
||||
splitter2.setSizes([1, 3])
|
||||
|
||||
splitter3.addWidget(splitter4)
|
||||
splitter3.addWidget(splitter8)
|
||||
splitter3.setSizes([2, 1])
|
||||
|
||||
splitter4.addWidget(splitter5)
|
||||
splitter4.addWidget(self.browser2)
|
||||
splitter4.setSizes([1, 3])
|
||||
|
||||
splitter5.addWidget(self.browser3)
|
||||
splitter5.addWidget(self.browser4)
|
||||
|
||||
splitter6.addWidget(self.browser5)
|
||||
splitter6.addWidget(splitter7)
|
||||
splitter6.setSizes([1, 2])
|
||||
|
||||
splitter7.addWidget(self.browser6)
|
||||
splitter7.addWidget(self.browser7)
|
||||
|
||||
splitter8.addWidget(self.browser8)
|
||||
splitter8.addWidget(splitter9)
|
||||
splitter8.setSizes([1, 2])
|
||||
|
||||
splitter9.addWidget(self.browser9)
|
||||
splitter9.addWidget(self.browser10)
|
||||
|
||||
main_box.addWidget(splitter1)
|
||||
self.setLayout(main_box)
|
||||
self.setGeometry(300, 300, 600, 500)
|
||||
|
||||
def setBackground(self):
|
||||
palette = QPalette()
|
||||
pix = QPixmap("./app/data/bg.png")
|
||||
pix = pix.scaled(self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) # 自适应图片大小
|
||||
palette.setBrush(self.backgroundRole(), QBrush(pix)) # 设置背景图片
|
||||
# palette.setColor(self.backgroundRole(), QColor(192, 253, 123)) # 设置背景颜色
|
||||
self.setPalette(palette)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
ex = MainWindow()
|
||||
sys.exit(app.exec_())
|
174
app/Ui/contact/analysis/charts.py
Normal file
174
app/Ui/contact/analysis/charts.py
Normal file
@ -0,0 +1,174 @@
|
||||
import datetime
|
||||
import os
|
||||
import random
|
||||
import time
|
||||
|
||||
import jieba
|
||||
from pyecharts import options as opts
|
||||
from pyecharts.charts import Pie, WordCloud, Calendar, Bar
|
||||
from pyecharts.faker import Faker
|
||||
from ....DataBase import data
|
||||
|
||||
data.mkdir(os.path.abspath('.') + '/data/聊天统计')
|
||||
|
||||
Type = {
|
||||
'1': '文字',
|
||||
'3': '图片',
|
||||
'43': '视频',
|
||||
'-1879048185': '微信运动排行榜',
|
||||
'5': '',
|
||||
'47': '表情包',
|
||||
'268445456': '撤回消息',
|
||||
'34': '语音',
|
||||
'419430449': '转账',
|
||||
'50': '语音电话',
|
||||
'100001': '领取红包',
|
||||
'10000': '消息已发出,但被对方拒收了。',
|
||||
'822083633': '回复消息',
|
||||
'922746929': '拍一拍',
|
||||
'1090519089': '文件',
|
||||
'318767153': '付款成功',
|
||||
'436207665': '发红包',
|
||||
'49': '分享链接'
|
||||
}
|
||||
|
||||
|
||||
def send_recv_rate(username):
|
||||
send_num = data.send_nums(username)
|
||||
recv_num = data.recv_nums(username)
|
||||
total_num = send_num + recv_num
|
||||
print(send_num, recv_num)
|
||||
c = (
|
||||
Pie(init_opts=opts.InitOpts(width="460px", height="240px"))
|
||||
.add(
|
||||
"",
|
||||
[
|
||||
('发送', send_num), ('接收', recv_num)
|
||||
],
|
||||
center=["40%", "50%"],
|
||||
)
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(title=f"信息发送接收",subtitle=f"总计:{total_num}条消息", pos_bottom="0%"),
|
||||
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
|
||||
)
|
||||
.set_series_opts(
|
||||
label_opts=opts.LabelOpts(formatter="{b}:{d}%"),
|
||||
)
|
||||
.render("./data/聊天统计/send_recv_rate.html")
|
||||
)
|
||||
|
||||
|
||||
def msg_type_rate(username):
|
||||
type_data = data.msg_type_num(username)
|
||||
type_data = sorted(type_data, key=lambda x: x[1], reverse=True)
|
||||
data1 = type_data[:4]
|
||||
data2 = sum(map(lambda x: x[1], type_data[4:]))
|
||||
print(type_data)
|
||||
new_data = []
|
||||
for t in data1:
|
||||
try:
|
||||
new_data.append((Type[str(t[0])], t[1]))
|
||||
except:
|
||||
new_data.append(('未知类型', t[1]))
|
||||
new_data.append(('其他', data2))
|
||||
|
||||
c = (
|
||||
Pie(init_opts=opts.InitOpts(width="460px", height="240px"))
|
||||
.add(
|
||||
"",
|
||||
new_data
|
||||
,
|
||||
center=["40%", "50%"],
|
||||
)
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(title=f"消息类型占比", pos_bottom="0%"),
|
||||
legend_opts=opts.LegendOpts(type_="scroll", pos_left="80%", orient="vertical"),
|
||||
)
|
||||
.set_series_opts(
|
||||
label_opts=opts.LabelOpts(formatter="{b}:{d}%"),
|
||||
)
|
||||
.render("./data/聊天统计/msg_type_rate.html")
|
||||
)
|
||||
|
||||
|
||||
def message_word_cloud(username):
|
||||
text = data.get_text(username)
|
||||
total_msg_len = len(text)
|
||||
word_list = jieba.cut(text)
|
||||
# word = " ".join(word_list)
|
||||
# print(word)
|
||||
stopwords = set()
|
||||
content = [line.strip() for line in open('./app/data/stopwords.txt', 'r', encoding='utf-8').readlines()]
|
||||
stopwords.update(content)
|
||||
wordcount = {}
|
||||
for word in jieba.cut(text):
|
||||
if len(word) > 1 and word not in stopwords:
|
||||
wordcount[word] = wordcount.get(word, 0) + 1
|
||||
text_data = sorted(wordcount.items(), key=lambda x: x[1], reverse=True)
|
||||
if len(text_data) > 100:
|
||||
text_data = text_data[:100]
|
||||
print(text_data)
|
||||
(
|
||||
WordCloud(init_opts=opts.InitOpts(width="900px", height="550px"))
|
||||
.add(series_name="聊天文字", data_pair=text_data, word_size_range=[20, 100])
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(
|
||||
title=f"词云图", subtitle=f"总计{total_msg_len}字",
|
||||
title_textstyle_opts=opts.TextStyleOpts(font_size=23)
|
||||
),
|
||||
tooltip_opts=opts.TooltipOpts(is_show=True),
|
||||
)
|
||||
.render("./data/聊天统计/wordcloud.html")
|
||||
)
|
||||
|
||||
|
||||
def calendar_chart(username):
|
||||
msg_data = data.get_msg_by_days(username)
|
||||
min_ = min(map(lambda x: x[1], msg_data))
|
||||
max_ = max(map(lambda x: x[1], msg_data))
|
||||
c = (
|
||||
Calendar(init_opts=opts.InitOpts(width="460px", height="255px"))
|
||||
.add(
|
||||
"",
|
||||
msg_data,
|
||||
calendar_opts=opts.CalendarOpts(range_="2022")
|
||||
)
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(title="2022年聊天情况"),
|
||||
visualmap_opts=opts.VisualMapOpts(
|
||||
max_=max_,
|
||||
min_=min_,
|
||||
orient="horizontal",
|
||||
# is_piecewise=True,
|
||||
# pos_top="200px",
|
||||
pos_bottom="0px",
|
||||
pos_left="0px",
|
||||
),
|
||||
)
|
||||
.render("./data/聊天统计/calendar.html")
|
||||
)
|
||||
|
||||
|
||||
def month_num(username):
|
||||
"""
|
||||
每月聊天条数
|
||||
"""
|
||||
msg_data = data.get_msg_by_month(username, year='2022')
|
||||
y_data = list(map(lambda x: x[1], msg_data))
|
||||
x_axis = list(map(lambda x: x[0], msg_data))
|
||||
c = (
|
||||
Bar(init_opts=opts.InitOpts(width="440px", height="245px"))
|
||||
.add_xaxis(x_axis)
|
||||
.add_yaxis("消息数量", y_data)
|
||||
# .add_yaxis("商家B", Faker.values())
|
||||
.set_global_opts(
|
||||
title_opts=opts.TitleOpts(title="逐月聊天统计", subtitle=None),
|
||||
datazoom_opts=opts.DataZoomOpts(),
|
||||
toolbox_opts=opts.ToolboxOpts(),
|
||||
)
|
||||
.render("./data/聊天统计/month_num.html")
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
send_recv_rate('wxid_wt2vsktnu4z022')
|
174
app/Ui/contact/analysis/pie_scroll_legend.html
Normal file
174
app/Ui/contact/analysis/pie_scroll_legend.html
Normal file
@ -0,0 +1,174 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Awesome-pyecharts</title>
|
||||
<script type="text/javascript" src="https://assets.pyecharts.org/assets/v5/echarts.min.js"></script>
|
||||
|
||||
</head>
|
||||
<body >
|
||||
<div id="ec5cb8f7096941f5ba51d65454d9c631" class="chart-container" style="width:470px; height:270px; "></div>
|
||||
<script>
|
||||
var chart_ec5cb8f7096941f5ba51d65454d9c631 = echarts.init(
|
||||
document.getElementById('ec5cb8f7096941f5ba51d65454d9c631'), 'white', {renderer: 'canvas'});
|
||||
var option_ec5cb8f7096941f5ba51d65454d9c631 = {
|
||||
"animation": true,
|
||||
"animationThreshold": 2000,
|
||||
"animationDuration": 1000,
|
||||
"animationEasing": "cubicOut",
|
||||
"animationDelay": 0,
|
||||
"animationDurationUpdate": 300,
|
||||
"animationEasingUpdate": "cubicOut",
|
||||
"animationDelayUpdate": 0,
|
||||
"aria": {
|
||||
"enabled": false
|
||||
},
|
||||
"color": [
|
||||
"#5470c6",
|
||||
"#91cc75",
|
||||
"#fac858",
|
||||
"#ee6666",
|
||||
"#73c0de",
|
||||
"#3ba272",
|
||||
"#fc8452",
|
||||
"#9a60b4",
|
||||
"#ea7ccc"
|
||||
],
|
||||
"series": [
|
||||
{
|
||||
"type": "pie",
|
||||
"colorBy": "data",
|
||||
"legendHoverLink": true,
|
||||
"selectedMode": false,
|
||||
"selectedOffset": 10,
|
||||
"clockwise": true,
|
||||
"startAngle": 90,
|
||||
"minAngle": 0,
|
||||
"minShowLabelAngle": 0,
|
||||
"avoidLabelOverlap": true,
|
||||
"stillShowZeroSum": true,
|
||||
"percentPrecision": 2,
|
||||
"showEmptyCircle": true,
|
||||
"emptyCircleStyle": {
|
||||
"color": "lightgray",
|
||||
"borderColor": "#000",
|
||||
"borderWidth": 0,
|
||||
"borderType": "solid",
|
||||
"borderDashOffset": 0,
|
||||
"borderCap": "butt",
|
||||
"borderJoin": "bevel",
|
||||
"borderMiterLimit": 10,
|
||||
"opacity": 1
|
||||
},
|
||||
"data": [
|
||||
{
|
||||
"name": "\u53d1\u9001",
|
||||
"value": 0.6
|
||||
},
|
||||
{
|
||||
"name": "\u63a5\u6536",
|
||||
"value": 0.4
|
||||
}
|
||||
],
|
||||
"radius": [
|
||||
"0%",
|
||||
"75%"
|
||||
],
|
||||
"center": [
|
||||
"40%",
|
||||
"50%"
|
||||
],
|
||||
"label": {
|
||||
"show": true,
|
||||
"margin": 8,
|
||||
"formatter": "{b}: {c}"
|
||||
},
|
||||
"labelLine": {
|
||||
"show": true,
|
||||
"showAbove": false,
|
||||
"length": 15,
|
||||
"length2": 15,
|
||||
"smooth": false,
|
||||
"minTurnAngle": 90,
|
||||
"maxSurfaceAngle": 90
|
||||
},
|
||||
"rippleEffect": {
|
||||
"show": true,
|
||||
"brushType": "stroke",
|
||||
"scale": 2.5,
|
||||
"period": 4
|
||||
}
|
||||
}
|
||||
],
|
||||
"legend": [
|
||||
{
|
||||
"data": [
|
||||
"\u53d1\u9001",
|
||||
"\u63a5\u6536"
|
||||
],
|
||||
"selected": {},
|
||||
"type": "scroll",
|
||||
"show": true,
|
||||
"left": "60%",
|
||||
"orient": "vertical",
|
||||
"padding": 5,
|
||||
"itemGap": 10,
|
||||
"itemWidth": 25,
|
||||
"itemHeight": 14,
|
||||
"backgroundColor": "transparent",
|
||||
"borderColor": "#ccc",
|
||||
"borderWidth": 1,
|
||||
"borderRadius": 0,
|
||||
"pageButtonItemGap": 5,
|
||||
"pageButtonPosition": "end",
|
||||
"pageFormatter": "{current}/{total}",
|
||||
"pageIconColor": "#2f4554",
|
||||
"pageIconInactiveColor": "#aaa",
|
||||
"pageIconSize": 15,
|
||||
"animationDurationUpdate": 800,
|
||||
"selector": false,
|
||||
"selectorPosition": "auto",
|
||||
"selectorItemGap": 7,
|
||||
"selectorButtonGap": 10
|
||||
}
|
||||
],
|
||||
"tooltip": {
|
||||
"show": true,
|
||||
"trigger": "item",
|
||||
"triggerOn": "mousemove|click",
|
||||
"axisPointer": {
|
||||
"type": "line"
|
||||
},
|
||||
"showContent": true,
|
||||
"alwaysShowContent": false,
|
||||
"showDelay": 0,
|
||||
"hideDelay": 100,
|
||||
"enterable": false,
|
||||
"confine": false,
|
||||
"appendToBody": false,
|
||||
"transitionDuration": 0.4,
|
||||
"textStyle": {
|
||||
"fontSize": 14
|
||||
},
|
||||
"borderWidth": 0,
|
||||
"padding": 5,
|
||||
"order": "seriesAsc"
|
||||
},
|
||||
"title": [
|
||||
{
|
||||
"show": true,
|
||||
"text": "\u53d1\u9001\u63a5\u6536\u5360\u6bd4",
|
||||
"target": "blank",
|
||||
"subtarget": "blank",
|
||||
"padding": 5,
|
||||
"itemGap": 10,
|
||||
"textAlign": "auto",
|
||||
"textVerticalAlign": "auto",
|
||||
"triggerEvent": false
|
||||
}
|
||||
]
|
||||
};
|
||||
chart_ec5cb8f7096941f5ba51d65454d9c631.setOption(option_ec5cb8f7096941f5ba51d65454d9c631);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Reference in New Issue
Block a user