聊天统计

This commit is contained in:
shuaikangzhou 2023-01-31 20:43:40 +08:00
parent 3cf9d5b475
commit d848a80b32
3 changed files with 484 additions and 0 deletions

View 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_())

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

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