共计 3340 个字符,预计需要花费 9 分钟才能阅读完成。
最近在做知识管理时遇到一个需求:需要将 ChatGPT 的历史对话导出保存。尝试了几种方法后,发现直接使用 API 会遇到各种问题,于是研究了一套完整的解决方案,今天把实战经验分享给大家。

1. 为什么需要专门的导出工具?
直接调用 ChatGPT API 获取对话记录时,主要会遇到这几个问题:
- 数据截断 :单次请求最多只能获取 100 条消息,长对话会被切断
- 格式混乱 :包含大量元数据和特殊标记,需要额外清洗
- 上下文丢失 :多轮对话的关联性无法保留
- 性能瓶颈 :连续请求容易触发 API 速率限制
这些问题让我们意识到,需要一个专门的导出工具来处理这些复杂性。
2. 技术方案选型
目前主要有两种实现方式:
- 官方导出工具 :
- 优点:开箱即用,支持基础格式
-
缺点:功能有限,无法自定义处理逻辑
-
自定义脚本 :
- 优点:完全可控,支持复杂场景
- 缺点:开发成本较高
考虑到项目需要处理大量对话和定制化需求,我们选择用 Python 开发自定义导出脚本。
3. 核心实现代码
以下是经过生产验证的完整实现(Python 3.8+):
import json
import csv
from typing import List, Dict, Optional
import requests
from pathlib import Path
class ChatGPTExporter:
"""ChatGPT 对话记录导出工具"""
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.openai.com/v1"
self.headers = {"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
def get_conversations(self, limit: int = 100) -> List[Dict]:
"""
分页获取对话列表
:param limit: 每页数量
:return: 对话列表
"""url = f"{self.base_url}/conversations"params = {"limit": limit}
all_conversations = []
while True:
response = requests.get(url, headers=self.headers, params=params)
response.raise_for_status()
data = response.json()
all_conversations.extend(data.get("items", []))
# 检查是否有更多数据
if not data.get("has_more"):
break
# 更新分页参数
params["after"] = data.get("last_id")
return all_conversations
def export_to_json(self, conversations: List[Dict], output_path: Path):
"""导出为 JSON 格式"""
with open(output_path, 'w', encoding='utf-8') as f:
json.dump(conversations, f, ensure_ascii=False, indent=2)
def export_to_csv(self, conversations: List[Dict], output_path: Path):
"""导出为 CSV 格式"""
# 提取需要导出的字段
processed = []
for conv in conversations:
processed.append({"id": conv.get("id"),
"title": conv.get("title"),
"create_time": conv.get("create_time"),
"update_time": conv.get("update_time")
})
# 写入 CSV
with open(output_path, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=processed[0].keys())
writer.writeheader()
writer.writerows(processed)
def export_to_markdown(self, conversations: List[Dict], output_path: Path):
"""导出为 Markdown 格式"""
with open(output_path, 'w', encoding='utf-8') as f:
for conv in conversations:
f.write(f"# {conv.get('title','Untitled')}\n\n")
f.write(f"- ID: {conv.get('id')}\n")
f.write(f"- Created: {conv.get('create_time')}\n")
f.write(f"- Updated: {conv.get('update_time')}\n\n")
# 获取对话详情
messages = self.get_messages(conv["id"])
for msg in messages:
f.write(f"## {msg['role'].capitalize()}\n")
f.write(f"{msg['content']}\n\n")
f.write("---\n\n")
def get_messages(self, conversation_id: str) -> List[Dict]:
"""获取单个对话的完整消息"""
url = f"{self.base_url}/conversations/{conversation_id}/messages"
response = requests.get(url, headers=self.headers)
response.raise_for_status()
return response.json().get("items", [])
# 使用示例
if __name__ == "__main__":
exporter = ChatGPTExporter(api_key="your_api_key_here")
conversations = exporter.get_conversations()
# 导出多种格式
exporter.export_to_json(conversations, Path("output.json"))
exporter.export_to_csv(conversations, Path("output.csv"))
exporter.export_to_markdown(conversations, Path("output.md"))
4. 性能优化技巧
处理大规模对话时,需要注意:
- 内存管理 :
- 使用生成器逐批处理数据
-
及时释放不再需要的对象
-
断点续传 :
- 记录最后导出的对话 ID
-
异常中断后可以从断点继续
-
速率控制 :
- 添加请求间隔(建议 0.5- 1 秒)
- 捕获 429 错误并自动重试
5. 常见问题解决方案
- API 返回空数据 :
- 检查认证是否正确
-
确认账号是否有访问权限
-
中文乱码 :
- 确保所有文件操作指定 utf- 8 编码
-
JSON 导出时设置 ensure_ascii=False
-
连接超时 :
- 增加超时时间(建议 30 秒)
-
实现自动重试机制
-
数据不完整 :
- 检查分页逻辑是否正确
-
验证 has_more 字段处理
-
导出速度慢 :
- 减少单次请求数据量
- 考虑使用并行请求(注意速率限制)
6. 安全注意事项
- 敏感数据 :对话可能包含个人信息,导出后需要妥善保存
- API 密钥 :不要硬编码在脚本中,建议使用环境变量
- 访问频率 :严格遵守 API 调用限制(通常每分钟 3 - 5 次)
下一步思考
成功导出对话数据后,如何更好地利用这些内容?这里有几个方向供参考:
- 集成到 Notion/Obsidian 等知识管理系统
- 构建本地搜索索引,方便快速检索
- 使用 NLP 技术进行自动分类和摘要
- 定期归档形成个人知识库
希望这篇文章能帮助你高效管理 ChatGPT 对话记录。如果有其他问题或优化建议,欢迎交流讨论!
正文完
发表至: 未分类
近三天内
