新闻详情

新闻详情

首页 / 资讯中心 / 详情

微信聊天记录导出为HTML、Word、CSV:从解密数据库到年度报告

发布时间:2026/10/2 17:46:49来源:尧图网络
微信聊天记录导出为HTML、Word、CSV:从解密数据库到年度报告
简介这份资源面向希望永久保存并深度利用微信聊天记录的用户以及想学习基于ChatGPT或私有部署大模型进行二次开发的开发者。它提供一套完整工具可将聊天记录导出为HTML、Word、CSV等格式长期归档并进一步分析生成年度聊天报告兼顾数据留存与趣味统计。压缩包共256个文件以103个Python源码为核心辅以61张PNG、43个SVG、18个HTML页面及若干Markdown说明、JSON配置与proto定义整体约25.4MB内含环境搭建教程代码注释清晰便于按模块阅读与二次修改。目前已有382人学习下载。通过源码与教程读者可掌握聊天记录解析、多格式导出、可视化报告生成等关键环节理解前后端交互与模型调用流程并借助现成脚本快速跑通项目适合具备一定Python基础、希望将LLM能力落地到实际场景的开发者参考实践。1. 微信聊天记录导出为 HTML、Word、CSV从解密数据库到年度报告的完整路径微信聊天记录里藏着大量有价值的信息可能是工作对接的关键凭证也可能是和朋友多年的情感存档。但微信本身并不提供批量导出功能一旦换手机、清缓存或者账号出现异常这些记录就可能永久消失。很多人直到需要翻某条记录时才发现自己根本没有后悔药可吃。这个方案要解决的问题很明确把微信聊天记录从本地数据库中提取出来解密后导出成 HTML、Word、CSV 三种格式永久保存并在此基础上做数据分析生成一份年度聊天报告。适合有一定动手能力、愿意折腾本地数据的从业者或技术爱好者。整个流程涉及数据库解密、数据解析、格式转换和可视化分析四个环节每一步都有具体的坑要踩下面逐层拆开讲。2. 微信聊天记录存储结构数据库在哪、加密方式是什么2.1 聊天记录到底存在哪个文件夹微信在 PC 端的聊天记录存储位置和手机端完全不同。PC 微信的历史版本比如 3.x 系列通常把数据放在「文档」目录下的WeChat Files文件夹里结构大致如下WeChat Files/ ├── All Users/ │ └── config/ ├── wxid_xxxxxxxxxxxx/ │ ├── Msg/ │ │ ├── Multi/ │ │ ├── Media/ │ │ └── ... │ ├── FileStorage/ │ ├── Image/ │ └── ...其中Msg目录下的Multi文件夹里存放的是聊天记录数据库文件扩展名通常是.db。这些数据库是 SQLite 格式但被加密过直接用 SQLite 工具打开会报错或者显示乱码。PC 微信 4.x 版本之后存储路径和加密方式都有调整部分版本会把数据放在xwechat_files目录下结构也有变化。所以第一步要做的就是确认自己电脑上微信的版本和对应的数据目录。常见做法是打开 PC 微信进入「设置」→「文件管理」查看「微信文件默认保存位置」。这个路径就是数据根目录。然后在该目录下找到以自己微信 ID 命名的文件夹进入Msg/Multi子目录就能看到若干.db文件。这些文件就是后续要处理的目标。注意操作前先完全退出微信否则数据库文件可能被锁定复制或读取时会失败。2.2 SQLite 加密机制与解密思路微信的聊天记录数据库使用的是 SQLite 格式但加了加密层。PC 端常见的是基于 SQLCipher 的加密方式密钥和微信账号、设备信息绑定。不同版本的密钥派生方式不同这也是整个流程中最容易翻车的环节。解密的基本思路是从微信进程的内存中提取密钥然后用密钥对数据库进行解密。常见做法有两种第一种是通过调试工具附加到微信进程在内存中搜索密钥特征。这种方法需要一定的逆向基础而且微信版本更新后密钥特征可能变化。第二种是使用社区维护的解密工具这些工具通常已经适配了多个微信版本输入数据库文件和微信账号信息后自动完成解密。我一般会优先选择第二种因为手动提取密钥的稳定性太差微信一更新就可能失效。解密完成后的数据库就是标准的 SQLite 文件可以用任何 SQLite 客户端打开。里面通常包含多张表核心表包括表名用途MSG存储聊天消息主体内容Contact存储联系人信息ChatRoom群聊信息Media媒体文件索引MSG表是最关键的表字段通常包括localId、TalkerId、Type、SubType、IsSender、CreateTime、StrContent、BytesExtra等。其中StrContent是文本内容BytesExtra是二进制扩展字段可能包含图片、文件等媒体信息的引用。2.3 解密后的数据长什么样解密后的MSG表里每条记录对应一条消息。Type字段标识消息类型常见取值1文本消息3图片消息34语音消息43视频消息49文件、链接、小程序等复合消息IsSender为1表示自己发送0表示对方发送。CreateTime是 Unix 时间戳需要转换成可读时间。StrContent在文本消息中就是消息正文在图片或视频消息中可能是 XML 格式的元数据。理解这些字段的含义是后续做数据导出和分析的基础。如果字段含义搞错了导出的内容就会张冠李戴。3. 导出为 HTML、Word、CSV三种格式的生成脚本与参数3.1 用 Python 读取解密后的数据库假设已经拿到了解密后的 SQLite 文件接下来用 Python 读取数据。需要安装sqlite3和pandaspip install pandas openpyxl python-docx读取MSG表并做初步清洗import sqlite3 import pandas as pd from datetime import datetime # 连接解密后的数据库 conn sqlite3.connect(decrypted_msg.db) cursor conn.cursor() # 查询消息记录按时间排序 query SELECT localId, TalkerId, Type, SubType, IsSender, CreateTime, StrContent, BytesExtra FROM MSG WHERE Type 1 ORDER BY CreateTime ASC df pd.read_sql_query(query, conn) # 时间戳转可读格式 df[CreateTime] df[CreateTime].apply( lambda x: datetime.fromtimestamp(x).strftime(%Y-%m-%d %H:%M:%S) ) # 标记发送方 df[Sender] df[IsSender].apply(lambda x: 我 if x 1 else 对方) print(f共读取 {len(df)} 条文本消息) conn.close()这段代码的逻辑是连接数据库查询Type1的文本消息按时间升序排列然后把 Unix 时间戳转成可读格式最后根据IsSender标记发送方。参数方面Type1只取文本消息如果需要包含图片、文件等类型可以去掉这个条件或改成Type IN (1,3,43,49)。TalkerId用于区分不同的聊天对象后续可以按这个字段分组导出。3.2 导出 CSV最直接的数据落地方式CSV 是最简单的导出格式适合后续用 Excel 或其他工具做二次分析# 导出为 CSV df.to_csv(chat_records.csv, indexFalse, encodingutf-8-sig) # 按聊天对象分别导出 for talker_id in df[TalkerId].unique(): subset df[df[TalkerId] talker_id] filename fchat_{talker_id}.csv subset.to_csv(filename, indexFalse, encodingutf-8-sig) print(f已导出 {filename}共 {len(subset)} 条)encodingutf-8-sig是为了让 Excel 打开 CSV 时不出现中文乱码。如果不需要按聊天对象拆分只保留第一行即可。按对象拆分的好处是当聊天对象很多时可以单独查看某一个人的记录不会混在一起。3.3 导出 HTML可读性最好的存档格式HTML 格式适合长期保存和浏览可以保留基本的排版和样式def export_to_html(df, output_file): html_header !DOCTYPE html html langzh-cn head meta charsetutf-8 title微信聊天记录/title style body { font-family: sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .msg { margin: 8px 0; padding: 8px 12px; border-radius: 8px; } .me { background: #95ec69; text-align: right; } .other { background: #fff; border: 1px solid #ddd; } .time { font-size: 12px; color: #999; } /style /head body html_footer /body/html rows [] for _, row in df.iterrows(): css_class me if row[Sender] 我 else other rows.append( fdiv classmsg {css_class} fdiv classtime{row[CreateTime]}/div fdiv{row[StrContent]}/div f/div ) with open(output_file, w, encodingutf-8) as f: f.write(html_header \n.join(rows) html_footer) print(f已导出 {output_file}) export_to_html(df, chat_records.html)这段代码生成一个带简单样式的 HTML 文件自己发送的消息靠右显示绿色气泡对方消息靠左显示白色气泡。css_class根据Sender字段动态切换。如果需要按聊天对象分别导出 HTML可以在循环中调用这个函数每次传入不同的子集。3.4 导出 Word适合打印和正式存档Word 格式适合需要打印或提交的场景用python-docx库生成from docx import Document from docx.shared import Pt, RGBColor def export_to_word(df, output_file): doc Document() doc.add_heading(微信聊天记录, level1) for _, row in df.iterrows(): p doc.add_paragraph() time_run p.add_run(f[{row[CreateTime]}] ) time_run.font.size Pt(9) time_run.font.color.rgb RGBColor(150, 150, 150) sender_run p.add_run(f{row[Sender]}) sender_run.bold True content_run p.add_run(str(row[StrContent])) content_run.font.size Pt(11) doc.save(output_file) print(f已导出 {output_file}) export_to_word(df, chat_records.docx)python-docx的参数控制比较直观Pt()设置字号RGBColor()设置颜色bold控制加粗。如果聊天记录量很大生成 Word 会比较慢建议先按时间范围或聊天对象筛选后再导出。4. 年度聊天报告从数据统计到可视化生成4.1 统计维度与数据聚合年度报告的核心是把原始消息数据聚合成有意义的统计指标。常见的维度包括统计项计算方式年度消息总数按年份筛选后计数月度消息分布按月份分组计数最活跃聊天对象按 TalkerId 分组计数取最大值消息类型占比按 Type 分组计数发送/接收比例按 IsSender 分组计数高频词对 StrContent 分词后统计词频用 pandas 做聚合# 提取年份和月份 df[Year] pd.to_datetime(df[CreateTime]).dt.year df[Month] pd.to_datetime(df[CreateTime]).dt.month # 年度消息总数 yearly_count df.groupby(Year).size() # 月度分布 monthly_count df.groupby([Year, Month]).size() # 最活跃聊天对象 top_talkers df.groupby(TalkerId).size().sort_values(ascendingFalse).head(10) # 发送接收比例 send_ratio df[IsSender].value_counts(normalizeTrue) print(年度消息总数) print(yearly_count) print(\n最活跃聊天对象 Top 10) print(top_talkers)这些统计结果可以直接输出到控制台也可以写入 HTML 报告模板。groupby的维度可以根据需要调整比如加上TalkerId和Month的交叉分组就能看到每个聊天对象的月度变化趋势。4.2 用图表展示年度数据纯数字不够直观加上图表会更有可读性。用matplotlib生成月度趋势图import matplotlib.pyplot as plt import matplotlib # 设置中文字体 matplotlib.rcParams[font.sans-serif] [SimHei] matplotlib.rcParams[axes.unicode_minus] False # 月度趋势图 monthly_data df.groupby(Month).size() plt.figure(figsize(10, 5)) plt.plot(monthly_data.index, monthly_data.values, markero) plt.title(年度月度消息趋势) plt.xlabel(月份) plt.ylabel(消息数量) plt.xticks(range(1, 13)) plt.grid(True, alpha0.3) plt.tight_layout() plt.savefig(monthly_trend.png, dpi150) plt.show()SimHei是中文字体如果不设置图表中的中文会显示成方块。dpi150控制输出图片的清晰度数值越高文件越大。生成的图片可以嵌入 HTML 报告中形成图文并茂的年度总结。4.3 把统计结果和图表组装成 HTML 报告最后一步是把所有统计结果和图表组装成一个完整的 HTML 文件def generate_report(df, output_file): # 计算各项统计 total len(df) yearly df.groupby(Year).size().to_dict() top_talkers df.groupby(TalkerId).size().sort_values(ascendingFalse).head(5) html f !DOCTYPE html html langzh-cn head meta charsetutf-8 title年度聊天报告/title style body {{ font-family: sans-serif; max-width: 900px; margin: 0 auto; padding: 20px; }} .card {{ background: #f8f9fa; border-radius: 12px; padding: 20px; margin: 16px 0; }} .number {{ font-size: 36px; font-weight: bold; color: #07c160; }} table {{ width: 100%; border-collapse: collapse; }} th, td {{ padding: 8px 12px; border-bottom: 1px solid #eee; text-align: left; }} /style /head body h1年度聊天报告/h1 div classcard p年度消息总数/p p classnumber{total}/p /div div classcard h2最活跃聊天对象/h2 table trth聊天对象/thth消息数/th/tr {.join(ftrtd{k}/tdtd{v}/td/tr for k, v in top_talkers.items())} /table /div div classcard h2月度趋势/h2 img srcmonthly_trend.png stylemax-width:100%; /div /body /html with open(output_file, w, encodingutf-8) as f: f.write(html) print(f报告已生成{output_file}) generate_report(df, annual_report.html)这个模板把消息总数、最活跃聊天对象和月度趋势图整合到一个页面里。f-string中的{{和}}是转义后的花括号因为外层用了 f-string。生成的 HTML 文件可以独立打开图片以相对路径引用所以需要把monthly_trend.png和 HTML 文件放在同一目录下。5. 避坑与排查解密失败、乱码、导出异常的 5 个典型问题5.1 数据库解密后打开仍然是乱码现象用解密工具处理后的.db文件用 SQLite 客户端打开表结构能看到但StrContent字段全是乱码或空白。原因解密不完整或者密钥不正确。部分微信版本的数据库有多个加密层只解了第一层。另外如果数据库文件在复制时没有完全退出微信文件可能处于写入状态复制出来的副本本身就不完整。解决先确认微信已完全退出重新复制数据库文件。然后检查解密工具是否适配当前微信版本必要时换一个工具或手动提取密钥。解密后先用sqlite3命令行执行.tables和SELECT COUNT(*) FROM MSG;验证数据完整性。5.2 导出的 CSV 用 Excel 打开中文乱码现象CSV 文件用文本编辑器打开正常但用 Excel 打开后中文变成乱码。原因Excel 默认使用系统编码简体中文 Windows 下是 GBK打开 CSV而文件是 UTF-8 编码两者不匹配。解决导出时加encodingutf-8-sig这个 BOM 头会告诉 Excel 文件是 UTF-8 编码。如果已经导出了可以用记事本打开 CSV另存为时选择「ANSI」编码或者用 Excel 的「数据」→「从文本/CSV」导入手动指定编码为 UTF-8。5.3 HTML 导出后图片和样式丢失现象HTML 文件在本地打开正常但发给别人或换一台电脑后图片不显示样式也乱了。原因HTML 中引用的图片是相对路径换环境后路径失效。样式如果写在外链 CSS 文件里同样会丢失。解决把 CSS 直接写在 HTML 的style标签里图片转成 base64 编码嵌入 HTML或者把图片和 HTML 打包到同一个文件夹一起发送。如果图片很多base64 会让 HTML 文件变得很大建议打包成 zip。5.4 消息时间戳转换后日期不对现象转换出来的时间比实际时间早了或晚了几个小时。原因datetime.fromtimestamp()默认使用本地时区如果数据库中的时间戳是 UTC 时间转换时没有加时区偏移就会出现偏差。解决确认时间戳的时区基准。如果是 UTC用datetime.utcfromtimestamp()或者手动加 8 小时。更稳妥的方式是用pytz或zoneinfo明确指定时区from datetime import datetime, timezone, timedelta tz timezone(timedelta(hours8)) dt datetime.fromtimestamp(ts, tztz)5.5 年度报告生成时内存不足现象聊天记录量很大几十万条生成报告时程序卡死或报MemoryError。原因一次性把所有数据读入内存加上分词和图表渲染内存占用过高。解决分批读取数据用pd.read_sql_query的chunksize参数分块处理。统计类操作可以用 SQL 的GROUP BY直接在数据库层面完成只把聚合结果读入内存。图表渲染用matplotlib的Agg后端避免弹出窗口占用额外资源。6. 进阶技巧用 SQL 直接做聚合减少 Python 内存压力当聊天记录达到几十万条时Python 端做groupby会越来越慢。一个更高效的做法是把聚合逻辑下推到 SQL 层Python 只负责展示结果。比如统计每个聊天对象的年度消息数SELECT TalkerId, COUNT(*) AS msg_count, SUM(CASE WHEN IsSender 1 THEN 1 ELSE 0 END) AS sent_count, SUM(CASE WHEN IsSender 0 THEN 1 ELSE 0 END) AS received_count, MIN(CreateTime) AS first_msg, MAX(CreateTime) AS last_msg FROM MSG WHERE Type 1 AND CreateTime strftime(%s, 2024-01-01) AND CreateTime strftime(%s, 2025-01-01) GROUP BY TalkerId ORDER BY msg_count DESC;这条 SQL 直接在数据库里完成了分组、计数、发送/接收统计和时间范围筛选返回的结果集很小Python 端只需要做格式化和展示。strftime(%s, 2024-01-01)把日期转成 Unix 时间戳和CreateTime字段的类型保持一致。如果数据库中的时间戳是毫秒级需要除以 1000 再比较。另一个实用技巧是建立索引。在MSG表的TalkerId和CreateTime字段上建索引可以大幅提升查询速度CREATE INDEX IF NOT EXISTS idx_msg_talker ON MSG(TalkerId); CREATE INDEX IF NOT EXISTS idx_msg_time ON MSG(CreateTime);索引会占用额外磁盘空间但对于几十万条以上的数据查询速度的提升非常明显。建索引的时机建议在解密完成后、开始分析之前避免在数据导入过程中反复重建。还有一个容易忽略的点StrContent字段中可能包含 XML 或 JSON 格式的复合消息直接当纯文本导出会带出一堆标签。可以在导出前做一次清洗用正则去掉标签只保留可读文本import re def clean_content(text): if not isinstance(text, str): return # 去掉 XML/HTML 标签 text re.sub(r[^], , text) # 去掉多余空白 text re.sub(r\s, , text).strip() return text df[StrContent] df[StrContent].apply(clean_content)这个清洗步骤放在导出之前对 HTML、Word、CSV 三种格式都适用。清洗后的文本更适合做词频统计和阅读。我自己在第一次做这个流程时最大的教训是低估了微信版本更新带来的兼容性问题。当时用了一个解密工具跑通了 3.9 版本的数据库结果微信自动升级到 4.0 后同样的工具直接报错折腾了大半天才找到适配新版本的方法。所以建议在操作前先关闭微信的自动更新或者把整个流程脚本化一旦某个环节失效能快速定位是解密、解析还是导出出了问题。另外导出后的文件建议按日期和聊天对象命名加上备份避免数据量大了之后自己都找不到哪个文件对应哪段对话。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

线性相关关系实战全解析:从相关系数到数据分析陷阱 2026/10/2 18:38:14

线性相关关系实战全解析:从相关系数到数据分析陷阱

今天聊一个数据分析里最常见、最常用,但也很容易被用错的概念—— 线性相关关系 。 我几乎每天都会处理数据,无论是业务报表、用户行为分析,还是实验评估,第一步几乎总是想看看两个变量之间有没有关系。比如投放金额和转化率、…

阅读更多 →
Android Release版APK构建全解析:签名、混淆与真机兼容性 2026/10/2 18:38:14

Android Release版APK构建全解析:签名、混淆与真机兼容性

1. 为什么“生成Release版APK”这件事,90%的Android新手都卡在第一步?你是不是也经历过:写完一个App,兴冲冲点下“Run”按钮,模拟器或真机上跑起来了,界面流畅、逻辑通顺——心里刚冒出“成了!”…

阅读更多 →
TypeScript TS7053报错:string索引类型与any类型解决方案 2026/10/2 18:38:14

TypeScript TS7053报错:string索引类型与any类型解决方案

写过 TypeScript 的人大概都遇到过这么一条报错:元素隐式具有 "any" 类型,因为类型为 "string" 的表达式不能用于索引类型。英文原版是Element implicitly has an any type because expression of type string cant be used to inde…

阅读更多 →
Python基于大数据的电影市场预测分析:从数据清洗到机器学习实战 2026/10/2 18:38:14

Python基于大数据的电影市场预测分析:从数据清洗到机器学习实战

1. 为什么选择“电影市场预测”作为实战项目 1.1 这个题目的核心价值 先聊聊选题这件事。很多同学找我聊课程设计或者毕业设计的时候,第一个问题就是“什么题目好过”。我通常不直接回答这个问题,而是反问一句: 你希望做完这个项目之后&…

阅读更多 →
Python电影票房预测项目实战:从爬虫到机器学习的完整数据分析链路 2026/10/2 18:38:14

Python电影票房预测项目实战:从爬虫到机器学习的完整数据分析链路

做数据分析项目,最容易踩的坑就是选题选得太抽象,数据难拿、结论难解释、技术栈还串不起来。我当初把“Python基于大数据的电影市场预测分析”定为实战项目,就是看中它能把爬虫、数据清洗、特征工程、机器学习和可视化整个链路全部打通。这个…

阅读更多 →
从DFT看懂OFDM:正交性、循环前缀与频域均衡 2026/10/2 18:38:02

从DFT看懂OFDM:正交性、循环前缀与频域均衡

我第一次接触 OFDM 时,教科书从多载波调制讲起,又是滤波器组又是正交条件,一节课听完,我脑子里只剩下一个问题:这么多子载波同时叠加在一起,接收端真的能一个不差地拆开吗?直到我把离散傅里叶变…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉