用SQL和Python分析五年微信聊天记录:从解密到数据可视化全流程
发布时间:2026/10/2 9:11:42来源:尧图网络
不知道你有没有过这种念头——手机里那几百 MB 的微信聊天记录除了“备份防丢”和“换机迁移”还能不能干点更有意思的事我前阵子正好把一台旧手机里五年的微信聊天记录整个导出来跑了一遍数据清洗和统计分析最后得到了一份带数字的个人社交“体检报告”谁聊得最多、深夜都在和谁说话、每年最热的词是什么全都一目了然。这篇随笔就把这套流程完整记录下来从怎么把聊天记录从手机里拿出来到数据库长什么样再到怎么用 SQL 和 Python 做统计可视化以及我踩过的那些坑。如果你也想对自己聊天记录做点“深度复盘”或者单纯是数据分析新手想找一个真实的练手数据集这篇文章应该能让你少走不少弯路。1. 为什么值得做微信聊天记录分析1.1 先搞清楚你分析的是“自己的数据”聊天记录是高度隐私的数据。所以做之前先立一条规矩只分析自己账号产生的对话不要碰别人的手机、账号和备份。自己这一份已经够玩了——五年十年攒下来的消息随便跑个统计都能看出很多名堂。为什么要专门说这个因为身边经常有人提“帮我分析一下我和对象谁先回消息”“看看我同事是不是经常摸鱼”之类的需求。这些一听就要拿别人数据的边界很模糊我从来不接。但自己的数据完全没问题既能玩得安心又能把整套技术链路走通。尤其对想练 SQL 和 Python 数据分析的朋友来说微信聊天记录是一个非常有真实感、复杂度适中、还自带情感温度的练习数据集。1.2 典型应用场景从“纪念”到“自查”这个项目能做的应用场景其实比想象中多我做过的大概有这么几类个人社交回顾统计聊天最频繁的 TOP10 联系人看看谁是你真正的“高频好友”。刚跑出来的时候我挺意外的排第一的不是我以为的那个人。作息与沟通习惯自查按小时统计发言量能清楚看到你几点最活跃。有人是凌晨灵感型有人是上班摸鱼型数据一出来特别真实。转账记录自动整理从消息里提取“转账”“收款”关键字配合红包记录可以做一份简单的个人收支小账本。纪念日与重要时刻提取把聊天中的照片、位置、链接、红包消息单独过滤出来重新串起一条时间线比相册回忆更有脉络。关系网络可视化把“谁和谁聊得最多”映射成关系图不但能看清自己的社交圈层还能顺便练一手图可视化。说白了聊天记录不只是聊天记录它是你近几年社交关系、生活节奏、消费习惯的一面镜子。只要把数据形态搞清楚玩法可以很丰富。1.3 一套完整流程的长什么样在动手之前建议先在脑子里把整条链路过一遍心里有底了再操作。数据链路大概是手机本机备份 → 从备份里提取微信数据目录 → 拿到核心数据库文件 → 解密或格式转换 → 用 SQL 查询 → 用 Python 做清洗和统计 → 最后可视化输出。这里最难的两个门槛一是“拿到数据”二是“能读懂数据”。前者通常卡在手机权限和备份方式上后者卡在数据库加密和表结构理解上。过了这两关后面的统计和可视化其实就是常规的数据分析操作了。所以下面我先把这两座大山翻过去。2. 数据获取先把聊天记录从手机里搬出来2.1 iOS 用户从本机备份里取出微信数据库iPhone 没有开放文件管理器常规做法是先用电脑对 iPhone 做一次完整备份。在 macOS 上用 Finder、在 Windows 上用 iTunes新版本叫 Apple Devices连接手机后选择“立即备份”。这里有一个关键选项是否勾选“加密本地备份”。不加密的备份微信数据库文件是明文存放的后续处理最省事加密备份会把备份包整体加密安全性高但后面分析时要额外处理密码而且密码忘了就没救了。我的建议是如果这台备份电脑只有你自己用就别勾加密纯分析场景图省心。备份完成后文件的存放路径是固定的。macOS 在~/Library/Application Support/MobileSync/Backup/下Windows 通常在C:\Users\你的用户名\Apple\MobileSync\Backup\下。目录看起来是一堆乱码哈希文件但你不需要逐个看直接全局搜索文件名EnMicroMsg.db就能定位微信数据库。部分版本的微信还会用到WxFileIndex.db一起找出来就行。2.2 Android 用户ADB 备份与系统自带备份Android 这边路径更直接一点但同样分情况。如果你的手机已经解锁了 root 权限微信的数据目录在/data/data/com.tencent.mm/下把整个目录拷出来就行了。这里要强调一句root 操作只建议在自己设备上做别拿别人的手机试。未 root 的手机可以尝试通过 ADB 备份接口拉数据。在电脑上装好 ADB 工具手机打开开发者模式和 USB 调试执行adb backup -f wx_backup.ab com.tencent.mm手机会弹出确认窗口输入备份密码后开始生成备份文件。这个方式在部分安卓版本和微信版本上会直接失败因为微信修改了备份策略但值得先试一把成本很低。另外很多国产手机系统自带“本地备份”或“手机搬家”功能可以在系统设置里做一个不含云端同步的本地完整备份再把备份文件拷贝到电脑上用厂商工具解开。这种方式兼容性最好缺点是需要装对应厂商的 PC 管理软件。2.3 拿到备份之后找什么不管哪种方式最后你都要在自己的本地磁盘上定位到微信的数据目录。iOS 备份解开后微信数据一般在对应 App 沙盒目录下的Documents/里。你会在里面看见EnMicroMsg.db、WxFileIndex.db以及voice、image、video、attachment等一堆媒体文件夹。真正承载消息记录的就是那个EnMicroMsg.db。Android 的目录结构更直白/data/data/com.tencent.mm/MicroMsg/下会有一个以 32 位哈希字符串命名的文件夹里面放着同样的EnMicroMsg.db和媒体目录。同一个手机如果有多个微信账号会有多个哈希目录注意别认错。2.4 开始前的准备清单磨刀不误砍柴工把下面这些准备好再开始一台用于备份和后续分析的电脑建议硬盘剩余空间不少于 20GB已经做过完整备份的旧手机如果备份还没做先做备份再继续读下去SQLite 图形化工具推荐 DB Browser for SQLite体积小不用安装Python 3.8 以上环境后面装pandas、matplotlib、jieba这几个库一个专门放备份数据的文件夹不要在磁盘根目录乱丢后面脚本要用3. 数据库解密与核心冰山EnMicroMsg.db 里的秘密3.1 数据究竟存在哪你可以把EnMicroMsg.db理解成一个超大号的 Excel 文件只不过它用的是 SQLite 格式。微信把消息、联系人、会话、公众号信息全都塞进了这一个文件里。如果直接用文本编辑器打开正常情况你会看到一堆乱码因为 SQLite 是二进制格式要用专门工具读取。更麻烦的是早期版本的微信还给这个数据库加了 SQLCipher 加密光有.db文件还不够得拿到密钥才能读。所以第一步不是急着写 SQL而是先确认文件头。用 DB Browser for SQLite 打开文件如果能看到“SQLite 3.x database”这个头部信息说明是明文库可以直接开搞。如果提示“file is not a database”或让你输入密码那说明还在加密状态需要先解决解密问题。3.2 核心表与字段你需要知道的四张表数据库打开后表会有一大堆但真正核心的没几张。我日常分析基本只看这几张message 表消息主表一条聊天记录一行。字段说明msgId消息唯一 IDtalker对方标识一般是一串 wxid 或原始 IDcontent消息文本内容部分类型存的是 XMLcreateTime时间戳单位是毫秒type消息类型数字编码isSend0 表示收到的消息1 表示自己发出的消息消息类型 type 是个很有用的字段常见值我整理了一下type含义1文本消息3图片消息34语音消息43视频消息49链接、文件、转账等富媒体消息500公众号/系统消息10000系统通知比如“你已添加了对方”rcontact 表联系人表存了昵称、备注、头像等。message.talker要和rcontact.username关联才能把一串 wxid 换成你认识的名字。chat_session 表会话概览表每个会话一行可以快速看会话数量适合做汇总。message_type 表消息类型名称对照表。如果不想自己记数字编码可以 JOIN 这张表查名字。3.3 解密逻辑简述早期版本早期版本的数据库加密逻辑其实不复杂网上很多一键解密工具的原理就是把手机硬件信息IMEI和微信账号标识uin拼起来取 MD5 的前 7 位作为 SQLCipher 密钥然后调 SQLCipher 接口打开数据库。具体一点IMEI 从/data/data/com.tencent.mm/shared_prefs/system_config_prefs.xml里读uin 从同目录的CompatibleInfo.cfg里拿然后MD5(IMEI uin)取前 7 位小写字符。但我要提醒一句这个算法是早期版本的方案新版微信已经反复调整过甚至同一版本在不同手机上表现都不一样。如果你手里的库解不开别死磕老算法直接去技术社区搜当前版本的处理方案或者换一条路在手机端先把聊天记录通过“迁移与备份”功能导出到另一台设备再从那边拿数据。分析的核心价值在于后面的统计思路和代码解密只是工程环节不值得耗一整天。4. 用 SQL 和 Python 做聊天记录统计与分析4.1 先写好这几条 SQL够你应付 80% 的统计需求数据库解开了分析就顺手了。我先给几条最常用的 SQL你直接在 DB Browser for SQLite 的“执行 SQL”标签里跑就能看到结果。统计每个会话的消息总量并按从多到少排序SELECT talker, COUNT(*) AS msg_count FROM message GROUP BY talker ORDER BY msg_count DESC LIMIT 20;看看你一天当中哪个小时最活跃SELECT strftime(%H, datetime(createTime / 1000, unixepoch, localtime)) AS hour, COUNT(*) AS cnt FROM message GROUP BY hour ORDER BY cnt DESC LIMIT 5;统计消息类型占比看看你的聊天里到底是文字多还是表情包多SELECT type, COUNT(*) AS cnt FROM message GROUP BY type ORDER BY cnt DESC;这几条能跑通你就已经迈过“不会查库”这道坎了。所有后续分析本质上都是这几条 SQL 的变身。4.2 Python 清洗把原始数据变成干净表格SQL 适合做聚合统计但要做词频、画图、清洗脏数据还得交给 Python。我最常用的库是sqlite3、pandas、jieba、matplotlib。第一步先把 message 表读成 DataFrame再把联系人的昵称关联进来。import sqlite3 import pandas as pd conn sqlite3.connect(EnMicroMsg.db) df pd.read_sql_query( SELECT m.msgId, m.talker, c.nickname, m.content, m.createTime, m.type, m.isSend FROM message m LEFT JOIN rcontact c ON m.talker c.username , conn) # 毫秒时间戳转成正常时间 df[time] pd.to_datetime(df[createTime], unitms) # 不转成东八区的话凌晨聊天会被算成前一天 df[time] df[time].dt.tz_localize(UTC).dt.tz_convert(Asia/Shanghai).dt.tz_localize(None) print(df.head())这一步完成你手里就有一张“每条消息是谁、什么时候、说了什么”的明细表后面所有统计都是在这张表上做筛选和聚合。4.3 找出“谁在深夜陪你说话”这是个很有画面感的统计。很多人手机里住着一个“深夜聊天对象”数据一跑就现原形。night df[(df[time].dt.hour 23) | (df[time].dt.hour 4)] top_night_chat night.groupby([talker, nickname]).size().reset_index(namenight_msg_count) top_night_chat top_night_chat.sort_values(night_msg_count, ascendingFalse) print(top_night_chat.head(10))我跑完这个统计发现自己凌晨时段聊得最多的人居然不是伴侣而是时差党朋友。数据不会骗人比主观印象准多了。你要是好奇自己“睡前最后一句话是发给谁的”还可以在同样的时段筛选条件里按时间倒序取每天最后一条消息记录。这个细节做出来拿来发朋友圈特别有梗。4.4 词频分析和“年度热词”词频统计需要先给中文分词。jieba是分词库能把一句话切成词然后再统计频率。import jieba from collections import Counter # 只统计文本消息并且是自己发的 texts df[(df[type] 1) (df[content].notna())][content].tolist() # 简单去一下表情符和多余空白 cleaned [str(t).replace(\u2005, ).strip() for t in texts if len(str(t)) 1] word_count Counter() for line in cleaned: word_count.update(jieba.lcut(line)) # 去掉常见停用词比如“嗯嗯”“哈哈哈”“在吗”这类 stopwords {嗯, 哈, 的, 了, 吗, 啊, 在, 是, 我, 你, 他, 她} hot_words [(w, c) for w, c in word_count.items() if w not in stopwords and len(w) 1] for word, cnt in hot_words[:20]: print(word, cnt)这里有个心得不要直接拿全量高频词当“年度热词”因为“哈哈哈”“嗯嗯”这类语气词会霸榜。加一个自定义停用词表或者按消息长度过滤一下基本就能剩下真正有意义的内容比如项目名、人名、经常念叨的事情。4.5 可视化让数字变成“看得见的社交画像”数据统计完画图是临门一脚。我常用matplotlib画 24 小时活跃分布再加一个月度趋势折线图。import matplotlib.pyplot as plt hourly df[time].dt.hour.value_counts().sort_index() plt.bar(hourly.index, hourly.values) plt.xlabel(hour) plt.ylabel(messages) plt.title(24h Chat Activity) plt.show()如果你想省事不写 Python 画图也可以。把df存成 CSVdf.to_csv(wechat_chat_log.csv, indexFalse, encodingutf-8-sig)然后拖进 Tableau、Power BI 或者腾讯云轻量 BI 这类工具里拖拽字段就能出图。数据分析这行有一条通用经验能用现成工具拖拽解决的就别自己重复造轮子。5. 常见问题与排查技巧实录5.1 问题速查表一路踩过来我遇到的坑基本都在这张表里了现象原因解决办法找不到 EnMicroMsg.db备份不完整或加密备份未解开重新做一次完整备份确认加密设置文件用 DB Browser 打不开文件被压缩或加密先看文件头确实加密就找解密方案时间显示成 1970 或 2027 年时间戳单位搞错应该除以 1000统一用createTime / 1000再转时间talker 是一串 wxid 不认识没关联联系人表LEFT JOIN rcontact后按 nickname 显示content 一堆 XML 标签type49 的富媒体消息正文包在 XML 里解析content里的title和des中文乱码读取或导出时编码不对用 UTF-8导出 CSV 用utf-8-sig兼容 ExcelisSend 看不出是谁发的没搞清方向定义0对方发来1自己发出这张表里最坑的就是时间戳单位。微信createTime存的是毫秒很多刚上手的人直接拿datetime.fromtimestamp(createTime)转结果日期全变成一九七几年。第一时间除以 1000能救你半小时。5.2 避坑技巧几个从实际操作中沉淀下来的细节常规文档里不会写。备份前先关掉云备份。我第一台 iPhone 做备份的时候iCloud 同步正开着结果电脑端备份和手机端云数据互相干扰导出来的库消息不全。正确的顺序是手机设置里暂时关掉“iCloud 云备份”再连电脑做完整备份分析完再打开。备份加密密码忘了等于白备。这一点再强调一遍也不为过。如果你勾了“加密本地备份”密码务必记牢。我身边有人密码忘了最后只能重置手机重新导聊天记录连备份恢复都做不了。不要把数据库放在手机上反复读。写脚本分析的时候先把 EnMicroMsg.db 复制到电脑本地。在手机上或备份目录里直接读一方面 IO 慢另一方面容易触发系统文件锁导致读到一半数据损坏。我是吃过这个亏的——跑了三个小时最后发现数据库在读取过程中被系统占用结果文件字节数都不对了。分享结果也要模糊隐私。发朋友圈晒图的时候把联系人昵称和聊天内容打码只保留统计数字。这既是保护自己也是保护跟你聊天的人。5.3 一条命令立刻看到结果如果你想先用最少的代码体验一下“分析聊天记录”的快感可以直接跑下面这段import sqlite3 import pandas as pd conn sqlite3.connect(EnMicroMsg.db) df pd.read_sql_query( SELECT c.nickname, COUNT(*) AS cnt, SUM(CASE WHEN m.isSend 1 THEN 1 ELSE 0 END) AS send_cnt, SUM(CASE WHEN m.isSend 0 THEN 1 ELSE 0 END) AS recv_cnt FROM message m LEFT JOIN rcontact c ON m.talker c.username GROUP BY m.talker, c.nickname ORDER BY cnt DESC LIMIT 10 , conn) print(df)输出的结果就是你的微信聊天 TOP10 联系人以及你们之间消息往来的总量、你发的条数和对方发的条数。看到那串数字的时候我第一次觉得原来自己的社交生活真的可以被量化。不过数据是数据它只能告诉你“和谁聊得多”并不能完全解释“和谁关系好”——比如家人群可能一天几十条都是鸡毛蒜皮真正重要的人反而未必刷屏。这也是我做完整个项目之后最大的体会统计分析是认识自己的工具但不该拿来给感情贴标签。
网站建设高端定制企业官网