Install
openclaw skills install @shaoqing404/gemini-openai-chat-export-analyze当用户要导出并分析与 Gemini(Google)或 ChatGPT(OpenAI)网页版的全部聊天历史时,加载本 skill。典型触发:用户提到 "导出 gemini 对话"、"gemini 聊天记录"、"chatgpt 数据导出"、"OpenAI conversations.json"、"我和 gemini/chatgpt 聊过什么"、"chatgpt 历史记录" 等。注意:本 skill 覆盖 ChatGPT 网页版与 Gemini 网页版(含 gemini.google.com 和 aistudio.google.com),不包括 API 调用记录或第三方客户端。
openclaw skills install @shaoqing404/gemini-openai-chat-export-analyze本 skill 覆盖两个产品:
| 产品 | 路径 | 产物 | 文件格式 |
|---|---|---|---|
| ChatGPT(OpenAI) | Settings → Data controls → Export | ZIP,内含 conversations.json 等 | JSON |
| Gemini(Google) | Google Takeout → Gemini Apps | ZIP,内含 My Activity/Gemini/*.html | HTML(不是 JSON) |
关键差异:ChatGPT 给 JSON,Gemini 给 HTML——本 skill 两套都要处理。
把跟 ChatGPT 的全部对话导出,大概走这几步:
- 打开 https://chatgpt.com(或 chat.openai.com)并登录
- 右上角点你的头像 → Settings
- 左侧菜单选 Data controls
- 找到 Export your data 区域,点 Request export
- 弹窗里勾上"Include chat history"(这是必须项),点 Confirm request
- 等 1~48 小时——OpenAI 会把下载链接发到你注册邮箱
- 邮件点链接下 ZIP,链接 7 天后失效,别拖
- ZIP 里找
conversations.json文件可能 10MB~1GB+,别打开,告诉我解压后的完整路径。
# 顶层是 array
jq 'type' /path/to/conversations.json
# → "array"
# 总数
jq 'length' /path/to/conversations.json
# 单条 session 字段(实测是这些,版本可能小变)
jq '.[0] | keys' /path/to/conversations.json
# 预期: ["create_time","default_model_slug","id","mapping","moderation_results","title","update_time","user_id"]
注意 ChatGPT 的结构和 Claude 完全不同:
mapping(嵌套树)而不是 chat_messages(线性数组)mapping.[id].message.author.role 里,值是 "user" / "assistant" / "tool"# 提取所有 user/assistant 消息,按树遍历顺序
jq -r '
.[] as $c
| $c.id as $cid
| $c.title as $title
| $c.create_time as $ct
| [
($c.mapping | to_entries[]
| .value.message
| select(. != null and .author.role != "tool")
| {
sender: (.author.role | if . == "user" then "human" else . end),
text: ([.content.parts[]? | select(type == "string")] | join("\n")),
created_at: (.create_time // null)
})
] as $msgs
| $cid + "|" + ($ct | tostring) + "|" + $title + "|" + ($msgs | length | tostring)
' /path/to/conversations.json
| 用户问题 | 对应处理 |
|---|---|
| 找关键词对话 | 用 jq 配合 test() 过滤 text 字段 |
| 列总览 | 用上面的"拍平"输出,按 create_time 排序 |
| 找强建议 | 搜 "我建议|建议你|不应该" |
| 找最长对话 | 排序 mapping 节点数 |
完整命令模板参见 claude-chat-export-analyze skill——结构差异处理完,jq 关键词搜索/时间线/主题提炼的逻辑完全通用。
把跟 Gemini 的全部对话导出,大概走这几步:
- 打开 https://myaccount.google.com 并登录
- 左上角菜单点 数据和隐私
- 向下滚到 数据下载(或"下载你的数据")区域,点进入 Google Takeout
- 取消全选,只勾 "我的活动"(My Activity)
- 点"我的活动"右边的下拉,确认"Gemini Apps"子项已勾选——只勾"Gemini"不一定包含完整对话
- 点 下一步,选 一次性导出、.zip 格式、大小 1~2GB/卷
- 点 创建导出
- 异步处理,可能几小时到几天,完成后 Google 邮箱会收到下载链接
- 下载 ZIP,解压后看
My Activity/Gemini/目录,里面是 HTML 文件(不是 JSON)提示我解压后的目录路径(整目录,不只是单个文件)。
Gemini 导出的是 HTML 不是 JSON——这是最大的坑。
# 先看目录里有什么
ls /path/to/My\ Activity/Gemini/
# 典型:My\ Activity.html 是单文件聚合,或者 Gemini\ Apps.html 等分文件
# 文件结构:每个 <div class="outer-cell"> 是一个对话轮次
用 python 快速解析:
from bs4 import BeautifulSoup
from pathlib import Path
import json, re
src = Path("/path/to/My Activity/Gemini")
out = []
for html_file in src.glob("*.html"):
soup = BeautifulSoup(html_file.read_text(encoding="utf-8"), "html.parser")
# 提取每条对话
cells = soup.find_all("div", class_=re.compile(r"outer-cell|content-cell"))
for cell in cells:
text = cell.get_text("\n", strip=True)
out.append({"file": html_file.name, "text": text})
print(json.dumps(out, ensure_ascii=False, indent=2))
或用 html2text:
html2text "/path/to/My Activity/Gemini/My Activity.html" > /tmp/gemini.txt
# 然后用 grep 搜
grep -n "我建议\|离职\|辞职" /tmp/gemini.txt
⚠️ 跟 ChatGPT / Claude 相比,Gemini 导出有几个明显短板:
如果用户要做严肃分析(时间线/语义检索),建议额外说明这些局限,或让用户优先用 ChatGPT/Claude 那边。
如果用户同时给了 Claude + ChatGPT + Gemini 三份数据,做"跨平台时间线"时:
import json, sys, re
from pathlib import Path
from datetime import datetime, timezone
def normalize(rec):
"""统一字段:sender, text, created_at, source, session_id, session_name"""
return {
"sender": "assistant" if rec["sender"] in ("assistant", "model", "gemini") else "human",
"text": rec["text"],
"created_at": rec["created_at"],
"source": rec["source"], # "claude" / "chatgpt" / "gemini"
"session_id": rec["session_id"],
"session_name": rec["session_name"],
}
# 然后写出 jsonl
with open("/tmp/unified.jsonl", "w", encoding="utf-8") as f:
for rec in records:
f.write(json.dumps(normalize(rec), ensure_ascii=False) + "\n")
# 在所有平台上找"离职"相关
grep -E "离职|辞职|跳槽" /tmp/unified.jsonl | head -20
# 按平台分布
jq -r '.source' /tmp/unified.jsonl | sort | uniq -c
# 按月份聚合
jq -r '.created_at[0:7]' /tmp/unified.jsonl | sort | uniq -c
.chat_messages[] 这种 Claude 习惯的语法1633072800 这种,需要 | todate 转jq 没法直接处理,先转文本message_feedback.json 包含用户 thumbs up/down——隐私敏感,不要 echo