mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-23 03:22:17 +08:00
个人年度报告新增性别和地区分布
This commit is contained in:
parent
fac0226edb
commit
040077dc7f
@ -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 = {}
|
||||
|
@ -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:
|
||||
|
@ -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]]
|
||||
|
@ -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}};
|
||||
|
@ -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,31 +39,44 @@ 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)
|
||||
contact =Contact(contact_info)
|
||||
print(detail)
|
||||
# region = contact.detail.get('region')
|
||||
# area = conversion_region_to_chinese(region)
|
||||
# print(area)
|
||||
return contact
|
||||
|
||||
|
||||
@app.route("/")
|
||||
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_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])
|
||||
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,
|
||||
'contact_topN': contact_topN,
|
||||
'contact_num':len(contact_topN_num),
|
||||
'send_msg_num':send_msg_num ,
|
||||
'receive_msg_num':total_msg_num-send_msg_num,
|
||||
'contact_num': len(contact_topN_num),
|
||||
'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>")
|
||||
|
Loading…
Reference in New Issue
Block a user