ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用Python把DeepSeek聊天记录做成年度报告:导出、清洗与可视化全指南

用Python把DeepSeek聊天记录做成年度报告:导出、清洗与可视化全指南 前几天整理电脑文件偶然翻出去年年初第一次打开 DeepSeek 时随手截的一张图。那时候还在想这玩意儿到底能干啥结果一年过去我发现自己每天说得最多的话居然不是跟同事不是跟家人而是跟这个对话框。于是我做了一个有点无聊但又特别上头的决定把这一整年的 DeepSeek 聊天记录全部导出来做成一份属于自己的年度报告。这篇文就记录一下完整的操作路线从导出、清洗、统计到可视化以及中间踩过的各种坑。适合所有想把自己和 AI 的对话数据变成一份可读报告的人也适合想做轻量级个人数据项目、但不知道从哪里下手的读者。1. 为什么要把聊天记录做成“数字年轮”1.1 聊天框里藏着最真实的年度流水账聊天记录这东西比日记诚实多了。日记还会斟酌措辞会隐藏情绪但深夜两点对着 AI 输出去的那句“为什么我写的代码又跑不通”是完全没有伪装的。我翻了一遍自己这一年的对话发现里面什么都有写公众号选题时的头脑风暴、改 bug 改到崩溃的抱怨、看论文时随手丢进去的 PDF 段落、过年回家做菜临时查的菜谱、甚至还有几次凌晨三点情绪低落的碎碎念。如果你也习惯把 DeepSeek 当成日常外挂大脑你的对话历史其实就是一份天然的个人数字痕迹。它记录了你关注什么、焦虑什么、什么时候最活跃、什么时候效率最高。比起朋友圈那种精心编排的年度总结聊天框里的数据更像流水账但恰恰是这种流水账才最接近真实的一年。1.2 参考音乐年度报告但不照搬很多人听到“年度报告”四个字第一反应是网易云音乐那种风格配色好看、文案扎心、能分享朋友圈。我承认这个形式确实值得借鉴但音乐报告能火靠的是“情绪共鸣数据惊喜”把一首歌和一个瞬间绑定起来。而聊天记录本身比播放记录私密得多也丰富得多它天然带着上下文每个数据背后都有一段具体的故事。所以我的设计原则很明确不追求页面多花哨追求“让数字替我说出这一年的变化”。比如凌晨三点的提问次数、提问里高频出现的报错信息、AI 回复里出现最多的那句“你可以尝试”这些数字堆在一起不需要华丽词藻就已经有冲击力了。你要做的只是把数据挖出来再用一个舒服的排版呈现给读者也就是你自己。2. 三步导出聊天记录三种方案与最终取舍2.1 方案一走官方 API 导出适合 API 重度用户如果你平时主要不是用网页对话框而是把 DeepSeek 接入到自己的工具链里那情况其实更简单。所有经过 API 的对话请求理论上都会经过你自己的服务端或调用日志。你只需要去捞自己的请求记录把 prompt 和 response 配对归档即可。我见过一些朋友会把这类调用记录直接存进数据库或者日志文件那一步基本等于免检。但大部分人——包括我——日常还是在网页端对话为主API 只用来跑一些自动化任务。这种情况下网页端的对话历史才是我最需要的原始数据源。注意如果你平时只调 API 但没有留存请求日志那这部分对话是找不回来的。我的习惯是从今天开始做请求日志归档哪怕只是把每次调用的输入输出追加到一个 JSONL 文件里年底做统计时就会非常省事。2.2 方案二浏览器开发者工具抓包适合网页端用户这是我最推荐的方案也是最终采用的主路径。原理很简单网页端的所有页面展示都得靠接口返回数据你只需要把那些接口拿到手就行。具体操作步骤用 Chrome 或 Edge 打开 DeepSeek 对话页面按 F12 打开开发者工具切到 Network 面板。在过滤栏里输入chat或session之类关键词把接口请求筛选出来。刷新页面或者点击左侧的会话列表观察哪几个请求返回了对话内容。找到返回 JSON 数据的请求右键 Copy选择 Copy as cURL或者直接在 Preview 面板里逐条查看。把所有会话的 JSON 响应保存到本地拼接成一个文件。这里有个关键点很多网页端的会话列表是分页懒加载的你必须手动滚动左侧列表让所有历史会话都被请求一遍否则导出的数据会缺一大截。我第一次抓的时候只滚了前几十条统计出来的对话量少得可怜后来才发现是没滚到底。2.3 方案三手动复制与第三方扩展备胎方案如果你的历史对话量不大手动复制粘贴也是一种办法。直接把对话内容粘贴进一个 txt 文件逐条整理就行。缺点显而易见效率低格式混乱。但胜在零门槛任何人都能做。另外浏览器扩展里有一些“一键导出 Chat 历史”的工具理论上能用但我不太推荐。倒不是工具本身有问题而是这类扩展通常需要读取你的页面数据权限安全上存在一定风险。如果你不在意隐私泄露那可以用如果在意的还是抓包或手动复制最稳妥。我最终的实际路径是主力用方案二抓包把网页端的 JSON 全量导出来方案一作为补充把我自己 API 调用日志里的对话也合并进去。两份数据合并后基本覆盖了我这一年的全部对话。3. 数据清洗将“聊天记录”变成“数据集”3.1 先搞懂导出的数据长什么样抓包拿到的 JSON一般结构是嵌套的最外层是会话列表里面每条会话包含标题、创建时间、更新时间以及一个 messages 数组。每个 message 对象大致有以下几个字段{ role: user, content: 为什么我的 Python 脚本运行这么慢, create_time: 1709273452000 }其中 role 有user和assistant两种分别代表你和 AIcontent 是文本正文create_time 是毫秒级时间戳。部分版本可能还会带model、tokens之类的字段统计时也能用到。搞清楚数据结构之后清洗工作就清晰了把 JSON 拆成一条条消息按时间排序区分角色剩下的就是统计的事。3.2 清洗思路与 Python 实现我平时不太写复杂脚本但应付这种数据清洗Python 加几个基础库就够了。核心操作可以分三步走。第一步读取 JSON 并遍历所有会话把所有消息合并到一个大列表里import json with open(deepseek_sessions.json, r, encodingutf-8) as f: sessions json.load(f) all_messages [] for session in sessions: for msg in session.get(messages, []): all_messages.append({ role: msg.get(role), content: msg.get(content, ), time: msg.get(create_time, 0) }) all_messages.sort(keylambda x: x[time]) print(f共解析到 {len(all_messages)} 条消息)如果你抓包时保存的是多个响应文件那就循环读取多个 JSON 文件再合并逻辑是一样的。第二步清洗内容字段。把常见的系统提示、空消息、纯 markdown 标记剔除掉尤其注意 content 里可能出现多余的换行符和转义字符import re def clean_content(text): # 去掉代码块标记 text re.sub(r[\w]*\n?, , text) # 去掉图片占位符 text re.sub(r!\[.*?\]\(.*?\), , text) # 压缩连续换行 text re.sub(r\n{3,}, \n\n, text) return text.strip() for msg in all_messages: msg[content] clean_content(msg[content])第三步做基础统计总消息数、用户消息数、AI 回复数、总字数、日均对话轮次等。这些数字本身就能撑起年度报告的一半内容。user_msgs [m for m in all_messages if m[role] user] assistant_msgs [m for m in all_messages if m[role] assistant] total_chars sum(len(m[content]) for m in all_messages) user_chars sum(len(m[content]) for m in user_msgs) print(f用户消息: {len(user_msgs)} 条总字数 {user_chars}) print(fAI 回复: {len(assistant_msgs)} 条总字数 {total_chars - user_chars})3.3 大文本处理要注意的坑有一年数据量大的话直接一次性把全部内容读进内存可能会卡顿。我自己的处理方式是分批统计比如按月把消息分组每个月单独算完再汇总这样既不占内存还能顺便做出“月度活跃度”数据。另一个坑是编码问题。Web 网页返回的 JSON 一般是 UTF-8但如果你的导出文件经过了某些编辑器保存可能变成 GBK 或带 BOM 头。读取时建议显式指定encodingutf-8遇到异常可以用errorsignore临时容错但最好还是把源文件统一转码一遍。还有一个小细节content 里可能出现\u2019这类 Unicode 编码的字符统计字数时不会被忽略需要先转成中文再清洗。用text.encode(utf-8).decode(unicode_escape)可以处理一部分但更稳妥的是直接在读取 JSON 时用ensure_asciiFalse的原始文件避免二次转义。4. 分析维度设计让数据替你讲故事4.1 时间维度你几点最活跃数据清洗完我第一个分析的维度是时间。把每条消息的create_time转换成可读时间然后按小时、按月做聚合统计。四小时维度的分析代码如下from datetime import datetime def hour_of(msg): return datetime.fromtimestamp(msg[time] / 1000).hour hour_counter {} for msg in user_msgs: h hour_of(msg) hour_counter[h] hour_counter.get(h, 0) 1 # 按小时输出 for h in range(24): count hour_counter.get(h, 0) bar # * (count // 5) print(f{h:02d}:00 {count:4d} {bar})分析出来之后我挺意外的。我一直觉得自己是夜间型选手但数据显示我白天上午十点左右的提问频率更高真正的高峰其实是下午三点前后。深夜当然也有一个次高峰集中在凌晨一点到两点而且那个时段的提问里“为什么”“报错”“怎么办”这类词占比明显更高。白天和黑夜的我完全两个状态。月份的维度我也做了用折线图看趋势会更直观。你能清楚看到哪几个月对话量暴增比如我赶项目的那几个月几乎每周的对话量都比平时翻倍也能看出哪个月基本没怎么用大概率是放假出去玩了。4.2 内容维度高频词与提问类型分类时间维度只是外壳真正有意思的是内容维度。这里我用到了 jieba 分词把全年所有的用户消息分词然后统计高频词。import jieba from collections import Counter stopwords set([什么, 怎么, 一个, 这个, 那个, 可以, 吗, 了, 我, 你]) words [] for msg in user_msgs: segs jieba.lcut(msg[content]) words.extend([w for w in segs if len(w.strip()) 1 and w not in stopwords]) counter Counter(words) for word, count in counter.most_common(30): print(f{word} {count})高频词出来之后你会立刻回忆起这一年的主题。我的前几名里有“代码”“部署”“报错”“端口”“写”“文章”“方案”基本就是我这一年工作的关键词。更细一点的还有“容器”“镜像”“接口”“权限”一眼就能看出哪个项目占了最大比重。光看词还不够直观所以我又做了一个粗粒度的类型分类。用正则规则把用户消息大致分成四类代码相关、写作相关、知识查询、情绪表达。分类逻辑不用做得太精确够用就行毕竟报告是给自己看的。def classify(text): if re.search(r代码|报错|bug|报错|接口|部署|函数|服务器|docker|端口, text): return code if re.search(r写|文章|标题|段落|措辞|润色|论文|稿子, text): return writing if re.search(r|吗|是什么|怎么样|为什么|为什么, text): return knowledge return emotion分类后的结果还挺有意思。我的提问里代码类占了四成多写作类两成知识查询两成剩下的情绪表达不到一成。但值得一提的是情绪类消息虽然数量最少平均长度却最长。就像跟朋友倾诉一样真正低落的时候你会打很多字。4.3 情感维度用 AI 分析 AI 的对话这是我整份报告里最特别的一块我把自己的聊天记录交给了 DeepSeek 本身去做情绪标注。做法不复杂把一段时间内的对话节选抽出来配合一段提示词让它判断我当时的心理状态。我用的提示词大概长这样下面是我某一天和 AI 的对话节选请判断我当天的主要情绪状态从平静、焦虑、兴奋、疲惫、好奇中选择一个并用一句话说明理由。 对话节选 {对话文本}然后按照返回结果打标再统计各个情绪状态的占比。这就是典型的 LLM-as-labeler 思路拿大模型当标注器用。人工给几千条对话逐条做情绪标注根本不现实但交给模型几十分钟就搞定了。出来的结果挺戳人的。数据显示我有一段时间的对话情绪大概率是“焦虑”翻回那几天的聊天记录果然都是在赶一个上线前的问题连续三四天每天都在问各种排查思路。看到那个数据的时候当时的那股焦躁感好像又重新涌上来了一点点。这种感觉是单纯看聊天记录体会不到的。5. 生成年度报告从图表到可分享的 HTML 页面5.1 报告页面放哪些板块最出效果统计分析做完之后就要考虑怎么呈现。我建议不要贪多报告的核心是让人一眼被击中。我最后保留的板块大概是这么几个总览数字和 DeepSeek 聊了多少次、你说了多少字、AI 回了多少字相当于写了多少篇长文。24 小时活跃热力你几点最活跃凌晨的提问占比。月度对话趋势一年 12 个月哪个月话最多。提问类型分布四类提问占比附一句我知道你今年在忙什么。年度高频词Top 词汇列表。年度之最你提出过的最长问题、AI 回复的最长答案以及那段内容的节选。年度关键词一年里出现频率最高的一个词配一句解读。每个板块我都在下方加了一句“人话解读”不是冷冰冰的图表而是像朋友在跟你聊天一样比如“这个月你的对话量翻了一倍应该是那件大事吧”。5.2 Python 出图matplotlib 实现中文可视化图表生成我用了 matplotlib核心就三步设置中文字体、绘图、保存成 base64 嵌入 HTML。下面是设置字体的部分import matplotlib.pyplot as plt plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False hours list(range(24)) counts [hour_counter.get(h, 0) for h in hours] plt.figure(figsize(10, 5)) plt.bar(hours, counts) plt.title(我的一天24小时对话分布) plt.xlabel(小时) plt.ylabel(消息数) plt.savefig(hour_dist.png, dpi150, bbox_inchestight)这里有个容易踩的坑如果系统没装 SimHei 字体中文标签会变成方块乱码。备选方案是改用系统自带的文泉驿或者微软雅黑或者在代码里指定字体路径。总之先跑一个小图测一下字体再批量生成所有图表别一口气画几十张图然后发现全乱码。指标图表生成之后我会用 base64 压缩成字符串直接嵌入 HTML这样最终只有单个文件发给任何人都能打开不存在跨设备打不开图片的问题。import base64 with open(hour_dist.png, rb) as f: img_data base64.b64encode(f.read()).decode(utf-8) img_html fimg srcdata:image/png;base64,{img_data} /5.3 用 HTML 模板拼装最终报告我会把整份报告设计成一个纵向滚动的页面类似电子杂志。配色上我用的是白底加深色文字加一个亮色渐变标题区。不用复杂框架纯 HTML 加一点内联 CSS 就够了。想省事的话也可以直接把 matplotlib 输出的 PNG 按顺序平铺在页面上配文字标题效果一样能打动人。这里分享一个排版技巧不要过度堆数据。数据分析结果往往很多但落到报告上只挑最有戏剧性的那部分。比如你不必把全部 24 小时的数据列出来只标注“最高点出现在下午三点最低点出现在上午 9 点”就够了。观众或者未来的你关心的不是数据完整性而是那些能唤起记忆的点。6. 常见问题与排查技巧实录6.1 抓包拿到的数据不完整怎么办最典型的症状是会话列表只有几十条明显少于你在页面上看到的会话数。原因基本可以确定是懒加载机制。解决办法很简单回到对话页面手动把左侧会话列表滚动到底触发所有分页请求。操作时注意看 Network 面板里是否持续出现新的会话请求直到滚到底部之后不再有新请求为止。然后再重新抓包导出。如果你的会话数量特别多比如上千个那滚动会比较辛苦。可以配合浏览器自动化工具模拟滚动操作把所有响应存下来再合并。6.2 时间戳对不上或时区错乱设备时区不同可能导致导出的时间戳和你的本地时间相差几个小时。大部分导出数据的时间戳用的是 Unix 毫秒时间戳本身是 UTC 时间转成当地时间需要根据你的时区做偏移。我的建议是清洗时统一用一个时区换算函数不要中途混用。同时注意一些特殊时段比如夏令时切换前后时间可能出现一小时的偏差。个人报告对时间精度要求不高但如果你按小时统计活跃度偏差一小时就会把高峰时段搞错。6.3 个人隐私如何脱敏这是很多人忽略但绝对不能忽略的问题。聊天记录里几乎肯定有你自己的真实姓名、同事昵称、项目代号、邮箱地址、手机号码甚至家庭住址。做报告之前务必做一轮脱敏处理。最简单的做法是用正则替换def desensitize(text): # 手机号脱敏 text re.sub(r(1[3-9]\d{9}), 138****8000, text) # 邮箱脱敏 text re.sub(r\b[\w.-][\w-]\.[\w.]\b, nameexample.com, text) return text如果是准备公开发布的报告建议把脱敏后的文案重新读一遍确保没有任何能关联到个人的信息残留。哪怕只是自己收藏脱敏后的版本也更安全万一哪天想分享给朋友不至于手忙脚乱。6.4 别人问我“这有什么用”时我的回答做这件事实诚地说没有直接的经济价值也不是某项工作需要交付的成果。但做完之后我对自己这一年的认知清晰了很多。这个价值没法用数字衡量。如果非要给它找点用它至少可以证明你不经意间留下的数据足够拼出一张“你究竟在忙什么”的画像。这些碎片化的消息本来是聊完就散的但把它们聚到一起竟然能拼出一个完整的人——一个会在深夜焦虑、会在白天拼命、会为了一个小问题纠结半天的你。我在实际做的时候还有一个体会技术社区里经常看到有人分享各种复杂的工作流工具用来编排和管理 DeepSeek 这类模型但对个人年度报告这种轻量项目完全没必要上那么重的方案。一个浏览器开发者工具、一个 Python 脚本、一堆 JSON 文件就能跑通全流程。越轻量的工具越容易坚持也越容易让你把注意力放在数据本身而不是工具上。最后再分享一个小技巧导出数据后记得第一时间做一份脱敏副本再开始排版。不然满屏都是自己的名字和项目代号你根本没法客观地看待这些数据总觉得每一条都在揭示什么。脱敏之后你反而能以旁观者的身份好好看看这一年到底是怎么过的。如果你也想做别想着一步到位先从“一个数字加一张图”开始跑通流程后再慢慢加维度和设计就已经比大多数人强了。
返回列表