diff --git a/app/Ui/contact/analysis/analysis.py b/app/Ui/contact/analysis/analysis.py new file mode 100644 index 0000000..c218531 --- /dev/null +++ b/app/Ui/contact/analysis/analysis.py @@ -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_()) diff --git a/app/Ui/contact/analysis/charts.py b/app/Ui/contact/analysis/charts.py new file mode 100644 index 0000000..7fa045c --- /dev/null +++ b/app/Ui/contact/analysis/charts.py @@ -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') diff --git a/app/Ui/contact/analysis/pie_scroll_legend.html b/app/Ui/contact/analysis/pie_scroll_legend.html new file mode 100644 index 0000000..7359cf2 --- /dev/null +++ b/app/Ui/contact/analysis/pie_scroll_legend.html @@ -0,0 +1,174 @@ + + +
+ +