mirror of
https://github.com/LC044/WeChatMsg
synced 2025-02-21 18:12:18 +08:00
增加五个数据统计接口
This commit is contained in:
parent
261ac8ea27
commit
8f12d9a3d0
@ -10,6 +10,7 @@ import html
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from app.log import logger
|
from app.log import logger
|
||||||
|
from app.util.compress_content import parser_reply
|
||||||
|
|
||||||
db_path = "./app/Database/Msg/MSG.db"
|
db_path = "./app/Database/Msg/MSG.db"
|
||||||
lock = threading.Lock()
|
lock = threading.Lock()
|
||||||
@ -153,7 +154,7 @@ class Msg:
|
|||||||
sql = '''
|
sql = '''
|
||||||
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
select localId,TalkerId,Type,SubType,IsSender,CreateTime,Status,StrContent,strftime('%Y-%m-%d %H:%M:%S',CreateTime,'unixepoch','localtime') as StrTime,MsgSvrID,BytesExtra,CompressContent
|
||||||
from MSG
|
from MSG
|
||||||
where StrTalker=? and Type=? and strftime('%Y',CreateTime,'unixepoch','localtime') = ?
|
where StrTalker=? and Type=? and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
|
||||||
order by CreateTime
|
order by CreateTime
|
||||||
'''
|
'''
|
||||||
else:
|
else:
|
||||||
@ -323,7 +324,7 @@ class Msg:
|
|||||||
from (
|
from (
|
||||||
SELECT MsgSvrID, CreateTime
|
SELECT MsgSvrID, CreateTime
|
||||||
FROM MSG
|
FROM MSG
|
||||||
where StrTalker = ? and strftime('%Y',CreateTime,'unixepoch','localtime') = ?
|
where StrTalker = ? and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?
|
||||||
)
|
)
|
||||||
group by hours
|
group by hours
|
||||||
'''
|
'''
|
||||||
@ -372,6 +373,155 @@ class Msg:
|
|||||||
lock.release()
|
lock.release()
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_send_messages_type_number(self, year_="all") -> list:
|
||||||
|
"""
|
||||||
|
统计自己发的各类型消息条数,按条数降序,精确到subtype\n
|
||||||
|
return [(type_1, subtype_1, number_1), (type_2, subtype_2, number_2), ...]\n
|
||||||
|
be like [(1, 0, 71481), (3, 0, 6686), (49, 57, 3887), ..., (10002, 0, 1)]
|
||||||
|
"""
|
||||||
|
|
||||||
|
sql = f"""
|
||||||
|
SELECT type, subtype, Count(MsgSvrID)
|
||||||
|
from MSG
|
||||||
|
where isSender = 1
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
group by type, subtype
|
||||||
|
order by Count(MsgSvrID) desc
|
||||||
|
"""
|
||||||
|
result = None
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
self.cursor.execute(sql, [year_] if year_ != "all" else [])
|
||||||
|
result = self.cursor.fetchall()
|
||||||
|
except sqlite3.DatabaseError:
|
||||||
|
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_chatted_top_contacts(self, year_="all", contain_chatroom=False, top_n=10) -> list:
|
||||||
|
"""
|
||||||
|
统计聊天最多的 n 个联系人(默认不包含群组),按条数降序\n
|
||||||
|
return [(wxid_1, number_1), (wxid_2, number_2), ...]
|
||||||
|
"""
|
||||||
|
|
||||||
|
sql = f"""
|
||||||
|
SELECT strtalker, Count(MsgSvrID)
|
||||||
|
from MSG
|
||||||
|
where strtalker != "filehelper" and strtalker != "notifymessage" and strtalker not like "gh_%"
|
||||||
|
{"and strtalker not like '%@chatroom'" if not contain_chatroom else ""}
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
group by strtalker
|
||||||
|
order by Count(MsgSvrID) desc
|
||||||
|
limit {top_n}
|
||||||
|
"""
|
||||||
|
result = None
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
self.cursor.execute(sql, [year_] if year_ != "all" else [])
|
||||||
|
result = self.cursor.fetchall()
|
||||||
|
except sqlite3.DatabaseError:
|
||||||
|
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_send_messages_length(self, year_="all") -> int:
|
||||||
|
"""
|
||||||
|
统计自己总共发消息的字数,包含type=1的文本和type=49,subtype=57里面自己发的文本
|
||||||
|
"""
|
||||||
|
|
||||||
|
sql_type_1 = f"""
|
||||||
|
SELECT sum(length(strContent))
|
||||||
|
from MSG
|
||||||
|
where isSender = 1 and type = 1
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
"""
|
||||||
|
sql_type_49 = f"""
|
||||||
|
SELECT CompressContent
|
||||||
|
from MSG
|
||||||
|
where isSender = 1 and type = 49 and subtype = 57
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
"""
|
||||||
|
sum_type_1 = None
|
||||||
|
result_type_49 = None
|
||||||
|
sum_type_49 = 0
|
||||||
|
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
self.cursor.execute(sql_type_1, [year_] if year_ != "all" else [])
|
||||||
|
sum_type_1 = self.cursor.fetchall()[0][0]
|
||||||
|
self.cursor.execute(sql_type_49, [year_] if year_ != "all" else [])
|
||||||
|
result_type_49 = self.cursor.fetchall()
|
||||||
|
for message in result_type_49:
|
||||||
|
message = message[0]
|
||||||
|
content = parser_reply(message)
|
||||||
|
if content["is_error"]:
|
||||||
|
continue
|
||||||
|
sum_type_49 += len(content["title"])
|
||||||
|
except sqlite3.DatabaseError:
|
||||||
|
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return sum_type_1 + sum_type_49
|
||||||
|
|
||||||
|
def get_send_messages_number_sum(self, year_="all") -> int:
|
||||||
|
"""统计自己总共发了多少条消息"""
|
||||||
|
|
||||||
|
sql = f"""
|
||||||
|
SELECT count(MsgSvrID)
|
||||||
|
from MSG
|
||||||
|
where isSender = 1
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
"""
|
||||||
|
result = None
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
self.cursor.execute(sql, [year_] if year_ != "all" else [])
|
||||||
|
result = self.cursor.fetchall()[0][0]
|
||||||
|
except sqlite3.DatabaseError:
|
||||||
|
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_send_messages_number_by_hour(self, year_="all"):
|
||||||
|
"""
|
||||||
|
统计每个(小时)时段自己总共发了多少消息,从最多到最少排序\n
|
||||||
|
return be like [('23', 9526), ('00', 7890), ('22', 7600), ..., ('05', 29)]
|
||||||
|
"""
|
||||||
|
sql = f"""
|
||||||
|
SELECT strftime('%H', CreateTime, 'unixepoch', 'localtime') as hour,count(MsgSvrID)
|
||||||
|
from (
|
||||||
|
SELECT MsgSvrID, CreateTime
|
||||||
|
FROM MSG
|
||||||
|
where isSender = 1
|
||||||
|
{"and strftime('%Y', CreateTime, 'unixepoch', 'localtime') = ?" if year_ != "all" else ""}
|
||||||
|
)
|
||||||
|
group by hour
|
||||||
|
order by count(MsgSvrID) desc
|
||||||
|
"""
|
||||||
|
result = None
|
||||||
|
if not self.open_flag:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
lock.acquire(True)
|
||||||
|
self.cursor.execute(sql, [year_] if year_ != "all" else [])
|
||||||
|
result = self.cursor.fetchall()
|
||||||
|
except sqlite3.DatabaseError:
|
||||||
|
logger.error(f'{traceback.format_exc()}\n数据库损坏请删除msg文件夹重试')
|
||||||
|
finally:
|
||||||
|
lock.release()
|
||||||
|
return result
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.open_flag:
|
if self.open_flag:
|
||||||
try:
|
try:
|
||||||
@ -386,16 +536,18 @@ class Msg:
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
db_path = "./Msg/MSG.db"
|
db_path = "./app/database/Msg/MSG.db"
|
||||||
msg = Msg()
|
msg = Msg()
|
||||||
msg.init_database()
|
msg.init_database()
|
||||||
result = msg.get_message_by_num('wxid_vtz9jk9ulzjt22', 9999999)
|
print(msg.get_chatted_top_contacts(year_="2023"))
|
||||||
print(result)
|
print(msg.get_chatted_top_contacts(year_="2023", contain_chatroom=True, top_n=20))
|
||||||
result = msg.get_messages_by_type('wxid_vtz9jk9ulzjt22', 49)
|
# result = msg.get_message_by_num("wxid_vtz9jk9ulzjt22", 9999999)
|
||||||
for r in result:
|
# print(result)
|
||||||
type_ = r[2]
|
# result = msg.get_messages_by_type("wxid_vtz9jk9ulzjt22", 49)
|
||||||
sub_type = r[3]
|
# for r in result:
|
||||||
if type_ == 49 and sub_type == 57:
|
# type_ = r[2]
|
||||||
print(r)
|
# sub_type = r[3]
|
||||||
print(r[-1])
|
# if type_ == 49 and sub_type == 57:
|
||||||
break
|
# print(r)
|
||||||
|
# print(r[-1])
|
||||||
|
# break
|
||||||
|
@ -389,13 +389,13 @@ class ChildThread(QThread):
|
|||||||
displayname = MePC().name if is_send else self.contact.remark
|
displayname = MePC().name if is_send else self.contact.remark
|
||||||
displayname = escape_js_and_html(displayname)
|
displayname = escape_js_and_html(displayname)
|
||||||
if self.output_type == Output.HTML:
|
if self.output_type == Output.HTML:
|
||||||
contentText = content.get('title')
|
contentText = escape_js_and_html(content.get('title'))
|
||||||
emojiText = findall(r"(\[.+?\])", contentText)
|
emojiText = findall(r"(\[.+?\])", contentText)
|
||||||
for emoji_text in emojiText:
|
for emoji_text in emojiText:
|
||||||
if emoji_text in emoji:
|
if emoji_text in emoji:
|
||||||
contentText = contentText.replace(emoji_text, emoji[emoji_text])
|
contentText = contentText.replace(emoji_text, emoji[emoji_text])
|
||||||
if refer_msg:
|
if refer_msg:
|
||||||
referText = f"{refer_msg.get('displayname')}:{refer_msg.get('content')}"
|
referText = f"{escape_js_and_html(refer_msg.get('displayname'))}:{escape_js_and_html(refer_msg.get('content'))}"
|
||||||
emojiText = findall(r"(\[.+?\])", referText)
|
emojiText = findall(r"(\[.+?\])", referText)
|
||||||
for emoji_text in emojiText:
|
for emoji_text in emojiText:
|
||||||
if emoji_text in emoji:
|
if emoji_text in emoji:
|
||||||
|
@ -46,7 +46,8 @@ def parser_reply(data: bytes):
|
|||||||
'type': '1',
|
'type': '1',
|
||||||
'content': '引用错误',
|
'content': '引用错误',
|
||||||
'displayname': '用户名',
|
'displayname': '用户名',
|
||||||
}
|
},
|
||||||
|
"is_error": True
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
root = ET.XML(xml_content)
|
root = ET.XML(xml_content)
|
||||||
@ -58,12 +59,13 @@ def parser_reply(data: bytes):
|
|||||||
refermsg_displayname = appmsg.find('refermsg').find('displayname').text
|
refermsg_displayname = appmsg.find('refermsg').find('displayname').text
|
||||||
return {
|
return {
|
||||||
'type': msg_type,
|
'type': msg_type,
|
||||||
'title': escape_js_and_html(title),
|
'title': title,
|
||||||
'refer': None if refermsg_type != 1 else {
|
'refer': None if refermsg_type != 1 else {
|
||||||
'type': refermsg_type,
|
'type': refermsg_type,
|
||||||
'content': escape_js_and_html(refermsg_content.lstrip("\n")),
|
'content': refermsg_content.lstrip("\n"),
|
||||||
'displayname': escape_js_and_html(refermsg_displayname),
|
'displayname': refermsg_displayname,
|
||||||
}
|
},
|
||||||
|
"is_error": False
|
||||||
}
|
}
|
||||||
except:
|
except:
|
||||||
return {
|
return {
|
||||||
@ -73,5 +75,6 @@ def parser_reply(data: bytes):
|
|||||||
'type': '1',
|
'type': '1',
|
||||||
'content': '引用错误',
|
'content': '引用错误',
|
||||||
'displayname': '用户名',
|
'displayname': '用户名',
|
||||||
}
|
},
|
||||||
|
"is_error": True
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user