个人年度报告新增性别和地区分布

This commit is contained in:
SiYuan 2024-02-13 22:34:45 +08:00
parent fac0226edb
commit 040077dc7f
5 changed files with 128 additions and 16 deletions

View File

@ -2,12 +2,16 @@ import os
from collections import Counter
import sys
from datetime import datetime
from typing import List
import jieba
from app.DataBase import msg_db, MsgType
from pyecharts import options as opts
from pyecharts.charts import WordCloud, Calendar, Bar, Line, Pie
from pyecharts.charts import WordCloud, Calendar, Bar, Line, Pie, Map
from app.person import Contact
from app.util.region_conversion import conversion_province_to_chinese
os.makedirs('./data/聊天统计/', exist_ok=True)
@ -415,6 +419,58 @@ def sender(wxid, time_range, my_name='', ta_name=''):
}
def contacts_analysis(contacts):
man_contact_num = 0
woman_contact_num = 0
province_dict = {
'北京': '北京市',
'上海': '上海市',
'天津': '天津市',
'重庆': '重庆市',
'新疆': '新疆维吾尔族自治区',
'广西': '广西壮族自治区',
'内蒙古': '内蒙古自治区',
'宁夏': '宁夏回族自治区',
'西藏': '西藏自治区'
}
provinces = []
for contact, num, text_length in contacts:
if contact.detail.get('gender') == 1:
man_contact_num += 1
elif contact.detail.get('gender') == 2:
woman_contact_num += 1
province_py = contact.detail.get('region')
if province_py:
province = province_py[1]
province = conversion_province_to_chinese(province)
if province:
if province in province_dict:
province = province_dict[province]
else:
province += ''
provinces.append(province)
print(province, contact.detail)
data = Counter(provinces)
data = [[k, v] for k, v in data.items()]
print(data)
max_ = max(list(map(lambda x:x[1],data)))
c = (
Map()
.add("分布", data, "china")
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="地区分布"),
visualmap_opts=opts.VisualMapOpts(max_=max_, is_piecewise=True),
legend_opts=opts.LegendOpts(is_show=False),
)
)
return {
'woman_contact_num': woman_contact_num,
'man_contact_num': man_contact_num,
'contact_region_map': c.dump_options_with_quotes(),
}
def my_message_counter(time_range, my_name=''):
msg_data = msg_db.get_messages_all(time_range=time_range)
types_count = {}

View File

@ -25,6 +25,7 @@ class Person:
self.avatar_path = None
self.avatar = None
self.avatar_path_qt = Icon.Default_avatar_path
self.detail = {}
def set_avatar(self, img_bytes):
if not img_bytes:
@ -55,6 +56,7 @@ class Person:
@singleton
class Me(Person):
def __init__(self):
super().__init__()
self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = ':/icons/icons/default_avatar.svg'
self.wxid = ''
@ -68,6 +70,7 @@ class Me(Person):
class Contact(Person):
def __init__(self, contact_info: Dict):
super().__init__()
self.wxid = contact_info.get('UserName')
self.remark = contact_info.get('Remark')
# Alias,Type,Remark,NickName,PYInitial,RemarkPYInitial,ContactHeadImgUrl.smallHeadImgUrl,ContactHeadImgUrl,bigHeadImgUrl
@ -81,7 +84,7 @@ class Contact(Person):
self.avatar = QPixmap()
self.avatar_path = Icon.Default_avatar_path
self.is_chatroom = self.wxid.__contains__('@chatroom')
self.detail = contact_info.get('detail')
self.detail:Dict = contact_info.get('detail')
self.label_name = contact_info.get('label_name') # 联系人的标签分类
"""
@ -97,6 +100,7 @@ class Contact(Person):
class ContactDefault(Person):
def __init__(self, wxid=""):
super().__init__()
self.avatar = QPixmap(Icon.Default_avatar_path)
self.avatar_path = ':/icons/icons/default_avatar.svg'
self.wxid = wxid
@ -106,6 +110,7 @@ class ContactDefault(Person):
self.smallHeadImgUrl = ""
self.smallHeadImgBLOG = b''
self.is_chatroom = False
self.detail = {}
class Contacts:

View File

@ -40,6 +40,7 @@ province_mapping = {
country_mapping = {
'CN': '中国大陆',
'TW': '中国台湾',
'GB': "英国",
}
city_mapping = {
"Beijing": "北京",
@ -326,12 +327,22 @@ city_mapping = {
"Jingdezhen": "景德镇",
"Xinyu": "新余",
"Yichun": "宜春",
"Fuzhou": "抚州"
"Fuzhou": "抚州",
"Tin Shui": "天水"
}
def conversion_province_to_chinese(province):
area = ''
if province in province_mapping:
area = f'{province_mapping[province]}'
return area
def conversion_region_to_chinese(region: tuple):
area = ''
if not region:
return area
if region[2]:
if region[2] in city_mapping:
area = city_mapping[region[2]]

View File

@ -8,6 +8,7 @@
<link rel="stylesheet" href="https://memotrace.lc044.love/static/css/fullpage.min.css" />
<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>
<script type="text/javascript" src="https://assets.pyecharts.org/assets/v5/maps/china.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<script type="text/javascript" src="https://memotrace.lc044.love/static/js/fullpage.min.js"></script>
<script type="text/javascript" src="https://davidshimjs.github.io/qrcodejs/qrcode.min.js"></script>
@ -31,6 +32,13 @@
align-items: center;
justify-content: center;
}
.slide{
margin: 0px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
#snow {
position: fixed;
top: 0;
@ -252,7 +260,7 @@ p {
}
.chart{
width: 800px;
height: 300px;
height: 500px;
}
.chart-container{
display: flex;
@ -264,7 +272,7 @@ p {
@media screen and (max-width:480px){
.chart{
width: 300px;
height: 250px;
height: 400px;
}
.chart-container{
display:flex;
@ -310,10 +318,18 @@ p {
<div class="section cover">
<h1>2023年</h1>
<p>你一共给<span class="number">{{contact_num}}</span>个联系人<br>发送了<span class="number">{{send_msg_num}}</span>条消息<br>收到了<span class="number">{{receive_msg_num}}</span>条消息<br>总计<span class="number">{{total_text_num}}</span></p>
<div class="chart-container">
<p><span class="number">{{man_contact_num}}</span>人 女<span class="number">{{woman_contact_num}}</span></p>
<div class="slide" data-anchor="slide1">
<div id="contact_region_map" class="chart" ></div>
</div>
<div class="slide" data-anchor="slide1">
<div id="types-chart" class="chart"></div>
</div>
<div class="slide" data-anchor="slide1">
<div id="sender-chart" class="chart" ></div>
</div>
</div>
<div class="section cover">
<h1>年度关键词</h1>
@ -390,10 +406,17 @@ p {
document.getElementById('types-chart'), 'white', {renderer: 'canvas'});
var result = {{chart_data_types|safe}};
chart_51ebd4312946429e9c32b2b55b96a479.setOption(result);
var chart_51ebd4312946429e9c32b2b55b96a479 = echarts.init(
document.getElementById('contact_region_map'), 'white', {renderer: 'canvas'});
var result = {{contact_region_map|safe}};
chart_51ebd4312946429e9c32b2b55b96a479.setOption(result);
var chart_51ebd4312946429e9c32b2b55b96a4 = echarts.init(
document.getElementById('sender-chart'), 'white', {renderer: 'canvas'});
var result = {{chart_data_sender|safe}};
chart_51ebd4312946429e9c32b2b55b96a4.setOption(result);
var chart_51ebd4312946429e9c32b2b55b96 = echarts.init(
document.getElementById('word_cloud'), 'white', {renderer: 'canvas'});
var result = {{chart_data_wordcloud|safe}};

View File

@ -7,9 +7,11 @@ from flask import Flask, render_template, send_file, jsonify, make_response, req
from pyecharts.charts import Bar
from app.DataBase import msg_db, micro_msg_db
from app.DataBase.hard_link import decodeExtraBuf
from app.analysis import analysis
from app.person import Contact, Me, ContactDefault
from app.util.emoji import get_most_emoji
from app.util.region_conversion import conversion_region_to_chinese
app = Flask(__name__)
@ -23,10 +25,12 @@ html: str = ''
api_url = 'http://api.lc044.love/upload'
def get_contact(wxid):
def get_contact(wxid) -> ContactDefault | Contact:
contact_info_list = micro_msg_db.get_contact_by_username(wxid)
if not contact_info_list:
return ContactDefault('')
detail = decodeExtraBuf(contact_info_list[9])
# detail = {}
contact_info = {
'UserName': contact_info_list[0],
'Alias': contact_info_list[1],
@ -35,8 +39,13 @@ def get_contact(wxid):
'NickName': contact_info_list[4],
'smallHeadImgUrl': contact_info_list[7],
'label_name': contact_info_list[10],
'detail': detail,
}
contact =Contact(contact_info)
print(detail)
# region = contact.detail.get('region')
# area = conversion_region_to_chinese(region)
# print(area)
return contact
@ -45,12 +54,20 @@ def index():
contact_topN_num = msg_db.get_chatted_top_contacts(time_range=time_range, top_n=9999999, contain_chatroom=True)
total_msg_num = sum(list(map(lambda x: x[1], contact_topN_num)))
contact_topN = []
for wxid, num in contact_topN_num:
contact = get_contact(wxid)
text_length = 0
contact_topN.append([contact, num, text_length])
contacts_data = analysis.contacts_analysis(contact_topN)
contact_topN = []
send_msg_num = msg_db.get_send_messages_number_sum(time_range)
contact_topN_num = msg_db.get_chatted_top_contacts(time_range=time_range, top_n=9999999, contain_chatroom=False)
for wxid, num in contact_topN_num[:6]:
contact = get_contact(wxid)
text_length = msg_db.get_message_length(wxid, time_range)
contact_topN.append([contact, num, text_length])
my_message_counter_data = analysis.my_message_counter(time_range=time_range)
data = {
'avatar': Me().smallHeadImgUrl,
@ -59,7 +76,7 @@ def index():
'send_msg_num': send_msg_num,
'receive_msg_num': total_msg_num - send_msg_num,
}
return render_template('index.html', **data,**my_message_counter_data)
return render_template('index.html', **data,**contacts_data, **my_message_counter_data)
@app.route("/christmas/<wxid>")