开源工具GetQzonehistory:用接口爬虫备份QQ空间全部说说
2026/9/19 9:52:56 网站建设 项目流程

如果你和我一样,混QQ空间的时间跨度超过十年,那你大概率遇到过这种场景:想翻翻某年某月发过的一条说说,结果往前翻了几十页,页面越滚越卡,图片加载不出来,早年的一些记录还被时间线折叠得找不到了。更尴尬的是,想做个年度回忆汇总,发现压根没有官方工具能把说说完整导出。这时候,一个叫GetQzonehistory的开源项目就派上了用场——它的用途非常纯粹:帮你把QQ空间发布过的历史说说,通过接口方式成批拉取下来,保存成结构化文件,留作本地备份或二次加工素材。

这篇文章我会直接从“这个项目值得用在哪里、它是怎么实现的、实际跑起来会遇到哪些坑”三个维度拆开讲。如果你只是想备份自己账号的说说,或者想基于QQ空间数据做个个人归档、年度总结、数据统计,这篇内容应该能帮你少走不少弯路。

1. 项目整体设计:它到底解决了什么问题

1.1 先说清楚需求:历史数据是会“消失”的

很多人的QQ空间里存着从初高中到工作后的完整记录,有些说说本身已经不只是“心情动态”,而是带着时间戳的个人编年史。我当初想备份的动机很简单:一是怕哪天账号出问题、数据被清;二是想把这些内容做成一个本地可检索的归档库,方便以后做时间线回顾。

但实际做的时候发现,腾讯官方并没有提供“导出全部说说”的便捷功能。靠网页端手动翻页复制,几千条说说不现实;用截图方式保存,图片和文字混在一起也没法检索。这时候,GetQzonehistory 这种以接口方式批量拉取数据的项目,就成了最靠谱的替代方案。它本质上做的事情,就是把你在浏览器里手动往下滚页面的过程,变成自动化循环请求后端接口,把返回的JSON数据解析后写入本地文件。

1.2 为什么用“接口爬虫”而不是UI自动化

你可能想问,既然要自动化,为什么不直接用 Selenium 这类浏览器自动化工具去跑网页?我起初也这么想过,但对比下来,接口方式优势非常明显:

  • 速度差异巨大。浏览器自动化要渲染整个页面、加载图片、执行前端脚本,翻一页可能花几秒钟;接口请求直接拿到JSON数据,很快就能拉完几千条说说。对于十万条级别的历史数据,这个时间差会非常明显。
  • 数据更干净。接口返回的是结构化数据,字段名称、时间戳、评论数、图片列表一清二楚;UI自动化还得从DOM节点里抠内容,容易因前端改版而失效。
  • 资源占用低。接口方式用一个Python脚本就能跑完,不需要额外安装浏览器驱动。

当然,接口方式也有前提——你得能拿到登录态凭证(Cookie),并且了解接口的参数规则。这正是 GetQzonehistory 这类项目帮你封装好的部分。

1.3 项目的整体执行流程

用一句话概括它的思路:把人工翻页变成循环请求。具体拆成四步:

  1. 获取登录QQ空间后的Cookie(相当于告诉服务器“我是谁”)。
  2. 用Cookie中的 key 计算出一个名为g_tk的参数(这是QQ空间接口的签名参数,防止未授权调用)。
  3. pos偏移量循环请求说说列表接口,每次拉取一批数据。
  4. 解析返回的JSON,把说说内容、发布时间、图片、来源设备等字段写入本地文件。

后面两章,我会逐个环节展开讲里面的细节。

2. 核心原理解析:说说是怎么被“抓”下来的

2.1 关键凭证:Cookie 和 g_tk 是怎么回事

首先要明确一个基础概念:QQ空间的说说列表数据,是通过网页端一个后端接口返回的。要请求这个接口,必须携带自己的登录Cookie,否则服务器会直接拒绝访问。Cookie相当于你在浏览器里留下的一串身份凭证,里面包含uin(你的QQ号)、p_skeyskey等字段。

g_tk是一个动态签名参数。它的作用是防止请求被第三方直接伪造,算是一个初级的风控校验。计算逻辑本质上是哈希加取模:把Cookie里的某个 key 值(一般是skeyp_skey)逐字符做运算。你可以把它通俗理解为“用Cookie里的密码串,生成一个临时令牌”。在项目里,一般会封装一个get_g_tk(cookie)方法,核心伪代码如下:

def get_g_tk(cookie_str): # 从cookie中提取skey或p_skey skey = extract_key(cookie_str, 'p_skey') or extract_key(cookie_str, 'skey') hash_val = 5381 for ch in skey: hash_val += (hash_val << 5) + ord(ch) return hash_val & 0x7fffffff

这里的哈希初始值和迭代方式,是QQ空间各个接口通用的规则。你在网上搜“QQ空间 g_tk 算法”能找到很多版本,基本都是同一套逻辑的变体。要注意的是,不同接口可能要求不同的key来计算,有的用skey,有的用p_skey,项目里通常都会自动做兼容处理。

2.2 说说列表接口的数据结构和分页机制

说说列表的核心接口长这样(以下地址基于实际分析补全):

https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?uin=你的QQ号&pos=0&num=20&g_tk=计算出的g_tk

关键参数有三个:

  • uin:目标QQ号,查自己就填自己的号。
  • pos:偏移量,从第几条开始拉取,相当于分页的页码。
  • num:本次拉取条数,一般建议20到40之间,调太大容易被风控。

接口返回的是JSON,里面有一个msglist数组,每个元素对应一条说说。常见的字段包括:

字段含义
content说说文本内容
createTime发布时间的时间戳
tid说说的唯一ID,可用于去重
source_name发布来源,比如“Android客户端”“iPhone”
pic图片列表,每个元素里包含原始图URL
cmtnumdatanum评论数、点赞数(部分版本字段名不同)
name发布者昵称
uin发布者QQ号

分页逻辑非常简单:第一次请求pos=0,拉20条;第二次pos=20,再拉20条,依次递增,直到返回的列表为空或不足一页为止。这种“偏移量分页”机制在早期接口里非常常见,它的优点是实现简单,缺点是如果你在拉取过程中有新增说说,会出现极少量的重复或移位,所以需要在本地再做一层去重处理。

2.3 数据解析与落盘:从接口到本地文件

拿到原始JSON之后,项目要做的事就是把非结构化数据转成结构化数据。最常见的输出格式有两种:

  • CSV/表格文件:一行一条说说,适合用Excel或NocoDB打开,做筛选和整理。
  • Markdown/HTML文件:按时间顺序生成一个可阅读的时间轴,适合保存成网页形式长期翻阅。

这里有一点要特别提醒:说说的content字段里可能包含HTML标签或转义字符,解析时需要做清洗。我在实际处理时遇到过部分说说内容里夹着<br/>&nbsp;这类HTML实体,直接展示会乱掉。建议在落盘时候统一做一次html.unescape()清洗,并把多张图片的URL拼接成可点击的链接格式。

还有一个容易被忽略的问题:图片链接默认可能带防盗链头。QQ空间的图片URL在浏览器里打开没问题,但如果要在本地程序里下载,最好在请求图片时加上Referer: https://user.qzone.qq.com/。否则会出现下载下来全是空文件或者403的情况。

3. 实操过程:从环境准备到跑通全流程

3.1 环境准备与依赖安装

这个项目对Python版本要求不高,3.7以上基本都能跑。核心依赖只有两个:requests用于发HTTP请求,pycookiecheat可选,用于从Chrome浏览器本地解密读取Cookie。我个人推荐的安装命令:

pip install requests pycookiecheat

建议用虚拟环境装,避免污染系统的Python。装完之后,把项目文件放到一个独立目录里,后续所有生成的数据文件都放在该目录下的output/文件夹中,方便管理。

3.2 获取登录Cookie的两种方式

这是整个过程中最容易卡住新手的一步。我实测下来有两种可用方式:

方式一:手动从浏览器复制(最稳妥)

在Chrome中登录user.qzone.qq.com,按 F12 打开开发者工具,切到 Network(网络)面板,刷新页面,点击任意一条请求,在 Request Headers 里找到Cookie字段,全选复制出来备用。注意,这个Cookie有效期的长短和你QQ空间的登录状态有关,有些环境几小时就会失效,有些可以持续几天。

方式二:通过扫码登录自动获取(更省事)

部分项目版本支持用pycookiecheat直接读取Chrome的本地Cookie,但你必须在电脑上已经登录过QQ空间,而且Chrome此时是关闭状态才能解密。这个方式受浏览器版本和系统影响较大,如果报错,直接退回方式一手动复制就行。手动复制反而是最不容易翻车的方案。

3.3 命令行运行与日志解读

准备就绪之后,运行命令类似这样(具体参数名以你拿到的项目内README为准):

python GetQzonehistory.py -u 你的QQ号 -c "这里粘贴完整的Cookie字符串"

如果项目支持从文件读取Cookie,更推荐把Cookie写入cookie.txt,然后用-f cookie.txt参数指定,避免明文命令被shell历史记录保存。运行后终端会逐页输出当前拉取的偏移量,比如:

INFO - 正在获取第 0 条,本次返回 20 条 INFO - 正在获取第 20 条,本次返回 20 条

看到“本次返回 0 条”或“已达末尾”之类的日志时,说明全部拉完了。整个过程里,如果中途断了,重新运行可能从头开始,所以建议先用小范围测试跑通流程,确认没问题后再全量执行。

3.4 结果文件说明与简单统计

跑完之后,输出目录下一般会生成类似qzone_history.csvqzone_history.md的文件。CSV里的列大概包括:发布时间、文本内容、来源设备、图片链接、说说ID。我习惯再补一个year列,方便后续按年份分组统计。

拿到数据之后,写个简单的统计脚本就可以把个人空间数据盘出花来:

import csv from collections import Counter with open('qzone_history.csv', encoding='utf-8') as f: rows = list(csv.DictReader(f)) print("说说总数:", len(rows)) # 年份分布 year_counter = Counter(row['create_time'][:4] for row in rows) for year in sorted(year_counter): print(year, year_counter[year])

实测下来,这种统计对做个人年度回顾非常有帮助,轻轻松松就能生成“哪一年发得最疯、哪一年开始变沉默”等时间线数据。

4. 常见问题与排查技巧实录

4.1 页面提示登录失效或返回错误码

这是最常见的报错。接口返回code不等于0,或者直接提示需要登录,大概率是Cookie失效了。我在实际使用中发现,一个Cookie经常上午还能用,下午就突然失效,这和账号异地登录保护机制有关。解决办法很简单:重新登录一次QQ空间,再复制最新的Cookie。如果频繁失效,可以减少并发条数,降低触发风控的概率。

4.2 拉到一半报错或被限制访问

当请求频率过高时,接口可能直接返回空数据、验证码页面或者retcode错误。遇到这种情况,别硬跑,先停几分钟,把每次请求之间加一个随机延时,比如:

import time import random time.sleep(random.uniform(0.5, 1.5))

这能显著降低触发限流的概率。另外,把单次num从20调小到10,虽然请求次数变多,但单次请求的负载更轻,反而更稳。

4.3 早年的说说拿不全,怎么办

这是一个比较扎心的事实:QQ空间接口对太过久远的数据(尤其是十年前左右的内容)存在返回限制,靠接口能查到的历史深度是有限的,未必覆盖你最早发的所有说说。如果发现某个年份之前的数据缺失,目前没有纯接口方案能解决,只能去网页端的“那年今日”或时间线里人工补。这也是我后来建议大家定期备份的原因——越早备份,归档越完整。

4.4 图片链接失效或下载失败

早期说说的图片链接可能因为存储策略调整而失效,这属于客观问题。能做的就是在拉取数据的同时,把图片同步下载到本地,减轻对原链接的依赖。下载时务必带好Referer头,否则很容易被防盗链拦截。图片文件名可以用“说说的发表时间+序号”来命名,对应关系记到CSV里,方便日后找回。

4.5 乱码与编码问题

如果你在Windows下运行脚本,打开CSV时用Excel显示乱码,通常是文件编码问题。建议在写文件时指定utf-8-sig编码,这样Excel直接双击打开就不会乱码了。如果你用Python读取,则统一用utf-8读取,保持一致。

下面是一份速查表,给遇到问题的人快速对照:

现象直接原因处理办法
返回code=-4000登录态失效重新获取Cookie并更换
拉到中途停止触发频率限制增加延时、调小num、暂停一段时间
早年数据缺失接口历史深度限制通过网页端手动补,建议尽早备份
图片下载403防盗链请求时加上QQ空间Referer
CSV用Excel打开乱码编码格式不兼容写入时使用utf-8-sig编码

5. 合规边界与后续扩展玩法

5.1 这个工具的使用边界,心里要有数

GetQzonehistory 这种项目的合规前提是:它只用于备份和整理你自己的QQ空间数据。擅自爬取、存储他人非公开信息,或者利用账号权限批量拉取陌生人数据,都存在账号安全和法律风险。我个人的实践准则就一条:这个工具只跑在自己的账号上,数据只留在自己本地。不要为了好奇去尝试抓别人空间的数据,封号是小问题,惹上法律纠纷就真不划算了。

5.2 扩展方向一:生成本地HTML时间轴

既然数据已经在手了,下一步就是让它好看可用。我写过一个小的脚本,把CSV渲染成类似日记时间轴的HTML页面:左侧是年份和月份,右侧是当月说说列表,包含文本和图片。整个页面是纯静态的,放在本地随时打开,完全脱离网络。有时候翻看十年前发的一句话,比社交APP的“那年今日”还要有感觉。

5.3 扩展方向二:和“说说恢复”“动态归档”结合起来

搜“qq空间说说恢复”这类需求的人,多半是误删了内容,想找回旧数据。如果你养成了定期用 GetQzonehistory 备份的习惯,那“恢复”就变成了本地数据回填的问题,根本不用依赖平台侧的恢复工具。我自己就是把备份文件按年份命名存放,比如qzone_2015.csvqzone_2016.csv,需要找某年内容直接搜索,效率非常高。

5.4 扩展方向三:个人数据统计和洞察

你还可以把备份数据玩出更多花样。比如,用可视化工具做一张“十年说说的情绪折线图”;又或者统计出你的高频发言时段,看看自己是不是典型的深夜感慨型用户;甚至可以提取说说里的地点信息,重构一份个人活动轨迹。这些扩展做起来不难,但前提是得有完整数据,而备份的价值此时就体现出来了。

5.5 一个提醒:自动化操作有风控,谨慎“折腾”

和GetQzonehistory同类思路的项目不少,包括“QQ等级加速脚本”“自动点赞”“群机器人”等,这些都属于自动化操作平台账号,存在触发风控、被封号的风险。GetQzonehistory这种低频拉取自己数据的场景风险较低,但也别高频反复跑。保持合理频率、遵守平台规则,才是长期稳妥使用的关键。

我个人在实际操作中的体会是:备份这件事,越早做越好。数据这种东西,平时感觉不到它多重要,等到真的需要翻出某年某月说过的那句话时,才发现丢失了就永久没了。如果你也想把自己QQ空间的记忆好好收起来,建议现在就拿这个项目跑一遍,把历史说说沉淀成自己手里实实在在的文件,哪怕只是放着不动,也是个安心。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询