微信聊天记录导出(2020新版)
微信聊天記錄導(dǎo)出(2020新版)
首先說明,坑的部分主要是數(shù)據(jù)庫破解。
項目地址:https://github.com/fly-dragon211/Wechat-message-analysis
1. 本地備份提取聊天記錄
這里主要講小米手機,蘋果手機參考https://www.zhihu.com/question/66251440,其他安卓手機可以用模擬器然后root提取。
要導(dǎo)出微信安卓客戶端的聊天記錄,首先得找到聊天記錄的數(shù)據(jù)庫。
 安卓客戶端的聊天記錄儲存在私有目錄 /data/data/com.tencent.mm/MicroMsg 下,這個目錄需要root權(quán)限才能進去,但是,那樣太太太麻煩了,好在我們MI6有本地備份的功能,利用這個功能。我們輕而易舉就可以獲得數(shù)據(jù)庫。
需要的工具
此處下載
首先到手機:設(shè)置->更多設(shè)置->備份和重置->本地備份 里面點擊新建備份,選擇軟件程序中的微信進行備份,注意只選擇微信。
然后到文件管理 /內(nèi)部儲存設(shè)備/MIUI/backup/ALLBackup/ 下將備份的文件夾復(fù)制到電腦
然后用任意一種壓縮包軟件(我用的是7zip)打開這個com.tencent.mm.bak文件,并且將apps\com.tencent.mm\r\MicroMsg\systemInfo.cfg、apps\com.tencent.mm\r\MicroMsg\CompatibleInfo.cfg和apps\com.tencent.mm\r\MicroMsg\xxxx\EnMicroMsg.db三個文件解壓到電腦上。這里xxxx是一串隨機的字母,代表你的微信用戶,每個人不一樣,一般是最大的那個文件夾,我這里是下圖所示文件夾:
2. 破解數(shù)據(jù)庫密碼
找到聊天數(shù)據(jù)庫了,但是目前還不能得到聊天記錄,因為這個數(shù)據(jù)庫是sqlcipher加密數(shù)據(jù)庫,需要密碼才能打開。
數(shù)據(jù)庫密碼有很多種生成方式:
手機IMEI+uin(微信用戶id userinformation) 將拼接的字符串MD5加密取前7位
如IMEI為123456,uin為abc,則拼接后的字符串為123456abc 將此字符串用MD5加密(32位)后
為df10ef8509dc176d733d59549e7dbfaf 那么前7位df10ef8 就是數(shù)據(jù)庫的密碼,由于有的手機是雙卡,有多個IMEI,或者當(dāng)手機獲取不到IMEI時會用默認(rèn)字符串1234567890ABCDEF來代替,由于種種原因,并不是所有人都能得出正確的密碼,此時我們可以換一種方法。
反序列化CompatibleInfo.cfg和systemInfo.cfg
不管是否有多個IMEI ,或者是微信客戶端沒有獲取到IMEI,而使用默認(rèn)字符串代替,微信客戶端都會將使用的信息保存在MicroMsg文件夾下面的CompatibleInfo.cfg和systemInfo.cfg文件中,可以通過這兩個文件來得到正確的密碼,但是這兩個文件需要處理才能看到信息。
使用hook方式得到數(shù)據(jù)庫的密碼,這個方法最有效參考
暴力破解
我開始用反序列化:
javac IMEI.java java IMEI systemInfo.cfg CompatibleInfo.cfg運行完成后就會得到密碼
 參考鏈接
但是出現(xiàn)了如下錯誤:
錯誤: 找不到或無法加載主類 IMEI 原因: java.lang.ClassNotFoundException: IMEI
于是我換了第一種方法,可是找不到uid
尋找uid
uid不是微信號,原來是保存在下面路徑:
/data/data/com.tencent.mm/shared_prefs/auth_info_key_prefs.xml,
在該文件中,鍵值“auth_uin”即為該用戶的uin。
但是我發(fā)現(xiàn)根本沒有這個路徑,可能是我的手機沒有root,于是我把備份的文件解壓,在里面搜索這個,終于找到了。
最終確定uid,然后MD5(IMEI少一位+uin)的輸出字符串作為密碼,取前7位小寫,就可以破解數(shù)據(jù)庫了。
得到數(shù)據(jù)庫之后可以分析一下你的聊天記錄,順便制作一個詞云來給你的心上人看一下你們都聊了啥👀
參考:
https://zhuanlan.zhihu.com/p/77418711
https://github.com/Heyxk/notes/issues/1
https://www.sohu.com/a/355273307_704736
數(shù)據(jù)分析
下面就是最關(guān)鍵的數(shù)據(jù)分析。聊天記錄包含了非常豐富的數(shù)據(jù),這里我只做了兩個比較簡單的例子,一個是針對時間做聊天時間段分布的統(tǒng)計;一個是針對內(nèi)容做字符匹配,統(tǒng)計一些高頻詞匯出現(xiàn)的次數(shù),比如“早安”、“晚安”、“想你”、“愛”等等(你懂的)。
詳情見本項目。代碼都有注釋,我寫了一個類把直方圖,高頻詞匯統(tǒng)計,詞云等結(jié)合起來了。
# -*- coding: utf-8 -*- """ Created on Sun Aug 16 10:41:08 2020 @author: fly """import numpy as np import pandas as pd import time import re import datetime import seaborn as sns import matplotlib.pyplot as plt from matplotlib.font_manager import * # 如果想在圖上顯示中文,需導(dǎo)入這個包 import xlwt import wordcloud # 詞云 import imageio import jieba # 中文分詞class WechatAnalysis:def __init__(self, data_frame, name):self.data_frame = data_frameself.wechat_name = nameself.chat_time, self.chat_content = self.get_time_and_content()self.font_path = r'C:\Windows\Fonts\MSYH.TTC' # 微軟雅黑def get_time_and_content(self):# 把聊天內(nèi)容和時間取出chat = self.data_framechat_time = []chat_content = []for i in range(len(chat) - 1):content = chat[i:i + 1]if content['talker'].values[0] == self.wechat_name:t = content['createTime'].values[0] // 1000 # 除以1000用以剔除后三位0c = content['content'].values[0]chat_time.append(t)chat_content.append(c)return chat_time, chat_contentdef get_time_hist(self, time_flag=0):""":param time_flag: 0 hour, 1 year day, 2 month:return:"""# 畫小時核密度分布圖str_list = ['小時', '天', '月']data_list = [self.to_struct_time(t)[time_flag] for t in self.chat_time] # 得到數(shù)據(jù)列表max_indx = np.argmax(np.bincount(data_list)) # 出現(xiàn)次數(shù)最多的數(shù)據(jù)max_num = np.bincount(data_list)[max_indx] # 出現(xiàn)次數(shù)print('\n.......................\n開始畫圖\n.......................')myfont = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC', size=22) # 標(biāo)題字體樣式myfont2 = FontProperties(fname=r'C:\Windows\Fonts\MSYH.TTC', size=18) # 橫縱坐標(biāo)字體樣式myfont3 = FontProperties(fname=r'C:\Windows\Fonts\FZSTK.TTF', size=18) # 標(biāo)注字體sns.set_style('darkgrid') # 設(shè)置圖片為深色背景且有網(wǎng)格線if time_flag == 0:sns.distplot(data_list, 24, color='lightcoral')plt.xticks(np.arange(0, 25, 1.0), fontsize=15)plt.ylabel('聊天概率', fontproperties=myfont2)elif time_flag == 1:sns.distplot(data_list, 365, kde=False, color='lightcoral')plt.xticks(np.arange(1, 366, 30), fontsize=15)plt.ylabel('消息條數(shù)', fontproperties=myfont2)plt.annotate("這%s我們發(fā)了%d條消息!" % (str_list[time_flag], max_num),xy=(max_indx,max_num), fontproperties=myfont3)elif time_flag == 2:sns.distplot(data_list, 12, kde=False, color='lightcoral')plt.xticks(np.arange(0, 12, 1.0), fontsize=15)plt.ylabel('消息條數(shù)', fontproperties=myfont2)plt.annotate("這%s我們發(fā)了%d條消息!" % (str_list[time_flag], max_num),xy=(max_indx, max_num), fontproperties=myfont3)plt.yticks(fontsize=15)plt.title('聊天時間分布', fontproperties=myfont)plt.xlabel('時間段/' + str_list[time_flag], fontproperties=myfont2)fig = plt.gcf()fig.set_size_inches(15, 8)fig.savefig('chat_time.png', dpi=100)plt.show()print('\n.......................\n畫圖結(jié)束\n.......................')def get_hour_slice(self):hour_set = [self.to_struct_time(t)[0] for t in self.chat_time]print('\n.......................\n開始聊天時段統(tǒng)計\n.......................')time_slice = [0, 0, 0, 0, 0, 0]deep_night = []for i in range(len(hour_set)):if 0 <= hour_set[i] < 6:time_slice[0] += 1deep_night.append([self.chat_time[i], self.chat_content[i]])elif 6 <= hour_set[i] < 10:time_slice[1] += 1elif 10 <= hour_set[i] < 14:time_slice[2] += 1elif 14 <= hour_set[i] < 18:time_slice[3] += 1elif 18 <= hour_set[i] < 22:time_slice[4] += 1else:time_slice[5] += 1labels = ['凌晨0點至6點', '6點至10點', '10點至14點','14點至18點', '18點至22點', '22點至次日凌晨0點']time_distribution = {labels[0]: time_slice[0],labels[1]: time_slice[1],labels[2]: time_slice[2],labels[3]: time_slice[3],labels[4]: time_slice[4],labels[5]: time_slice[5]}for label in labels:print("{ name: '%s': %d}, \n" % (label, time_distribution[label]))''' 深夜聊天記錄 '''wbk = xlwt.Workbook()sheet = wbk.add_sheet('late')for i in range(len(deep_night)):sheet.write(i, 0, time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(deep_night[i][0])))sheet.write(i, 1, deep_night[i][1])wbk.save('聊得很晚.xls')print('\n.......................\n聊天時段統(tǒng)計結(jié)束\n.......................')def get_word_cloud(self, chinese_slice=False, stopwords=None, image_out_name=None):""":param chinese_slice: Whether Use jieba to slice the sentences.:param stopwords: a set include some words to exclude.:return:"""font_path = self.font_pathif image_out_name is None:image_out_name = 'word-heart.png'if chinese_slice:text = ",".join(self.chat_content)text_list = jieba.lcut(text)text = " ".join(text_list)image_out_name = 'zh-'.__add__(image_out_name)else:text = " ".join(self.chat_content)mk = imageio.imread("heart.png")# 構(gòu)建并配置詞云對象w,注意要加scale參數(shù),提高清晰度w = wordcloud.WordCloud(width=1000,height=700,background_color='white',font_path=font_path,mask=mk,scale=2,stopwords=stopwords,contour_width=1,contour_color='red')# 將string變量傳入w的generate()方法,給詞云輸入文字w.generate(text)# 展示圖片# 根據(jù)原始背景圖片的色調(diào)進行上色image_colors = wordcloud.ImageColorGenerator(mk)plt.imshow(w.recolor(color_func=image_colors))# 根據(jù)原始黑白色調(diào)進行上色# plt.imshow(wc.recolor(color_func=grey_color_func, random_state=3), interpolation='bilinear') #生成黑白詞云圖# 根據(jù)函數(shù)原始設(shè)置進行上色# plt.imshow(wc)# 隱藏圖像坐標(biāo)軸plt.axis("off")plt.show()# 將詞云圖片導(dǎo)出到當(dāng)前文件夾w.to_file(image_out_name)def get_word_statistic(self):''' 字符統(tǒng)計 '''chat_content = self.chat_contentchat_time = self.chat_timeprint('\n..........\n開始字符統(tǒng)計\n............\n')start = datetime.datetime.now()pattern_love = '.*?(愛).*?'pattern_morning = '.*?(早).*?'pattern_night = '.*?(晚安).*?'pattern_miss = '.*?(想你).*?'pattern_set = [pattern_love, pattern_morning, pattern_night,pattern_miss, '.*?(在干嘛).*?', '.*?(嘻嘻).*?']statistic = list(np.zeros(len(pattern_set), dtype=np.int))for i in range(len(chat_content)):for j in range(len(pattern_set)):length = len(re.findall(pattern_set[j], str(chat_content[i])))statistic[j] += lengthprint("在%d個日日夜夜里" % ((max(chat_time) - min(chat_time)) // (3600*24)))for i, pattern in enumerate(pattern_set):print("我們說了%d次 %s" % (statistic[i], pattern.strip('.*?()')))end = datetime.datetime.now()print('\n..........\n字符統(tǒng)計結(jié)束,用時: {}\n............\n'.format(end - start))@staticmethoddef to_struct_time(t):struct_time = time.localtime(t) # 將時間戳轉(zhuǎn)換為struct_time元組hour = round((struct_time[3] + struct_time[4] / 60), 2)month = struct_time.tm_monyday = struct_time.tm_ydayreturn hour, yday, monthif __name__ == '__main__':myGirl = '微信UID !!!'csv_path = '你導(dǎo)出的csv文件'chat = pd.read_csv(csv_path, sep=',', encoding='utf-8', usecols=[6,7,8])# createTime talker content‘ dtype: float, string,stringWechat = WechatAnalysis(chat, myGirl)# Get the hour distributionWechat.get_time_hist()Wechat.get_hour_slice()# Get word cloudplt.figure(2)Wechat.get_word_cloud() # Not slice the chinese wordsplt.figure(3)Wechat.get_word_cloud(stopwords={'嘻嘻', '嗯嗯', '嗯呢', '這樣子', '這樣子呀', '捂臉'})Wechat.get_word_statistic()參考:
總結(jié)
以上是生活随笔為你收集整理的微信聊天记录导出(2020新版)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 计算机中模板与母版的区别,模板和模版有啥
 - 下一篇: 微信小程序约课_基于微信小程序的瑜伽馆约