news 2026/10/18 18:01:35

Python脚本一键获取QQ号全部群组列表:原理、实现与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python脚本一键获取QQ号全部群组列表:原理、实现与避坑指南

简介:一套面向Python爬虫初学者及数据分析师的轻量脚本工具,用于根据指定QQ号批量查询其加入的全部群组信息,免去逐群手动翻看资料的重复劳动。其中qq_count.py负责快速校验目标账号有效性并初步感知其活跃群关系,qq_count_detail.py则进一步抓取群ID、群名称、成员数与创建时间等结构化字段,运行依赖requests、bs4、lxml,并需要手动导入Cookie或扫码登录后的session信息完成身份验证。压缩包仅7KB,共6个文件,包括2个Python核心脚本、1个依赖清单txt、1个含详细使用步骤与常见报错处理的README文档,以及环境与辅助配置项。已有94人学习;数据最终以JSON格式本地保存,便于直接导入Excel或数据库做二次分析。配合文档还可明确账号信息自查与授权数据整理场景下的合规边界,适合需要沉淀QQ群关系脉络的个人开发者或轻量级调研项目。

1. 一键获取指定QQ号的全部群组列表:它做的是信息聚合,不是入侵

把一串QQ号丢进去,几分钟后就能拿到这个号加入过的所有群名称、群号、群成员数、入群时间——这个Python脚本做的事情,本质是把你手动点开个人资料卡、再逐个翻“QQ群”标签页的重复劳动,压缩成一次自动化的接口调用。对于做账号资产梳理、用户运营分层、甚至自己的多账号管理来说,这能省下大量机械操作时间。它适合两类人:一类是需要在合规授权下批量核对群归属的运营或风控人员,另一类是研究QQ Web接口协议的开发者。但先说清楚:脚本只走官方公开的Web接口,不碰任何破解或注入,能不能取到数据,完全取决于登录态和账号本身的权限边界。

2. 原理与选型:为什么走Web接口而不是Hook客户端

2.1 接口链路梳理:从登录态到群列表的完整请求链

拿到一个QQ号后,脚本要回答第一个问题:这个账号允许我看它的群列表吗?在QQ的开放生态里,普通用户查看他人公开资料时,能看到部分群信息,但完整群列表通常需要满足两个条件:对方在你的好友列表中,或者对方开启了“允许陌生人查看群聊”的公开选项。脚本的实现思路不是暴力破解,而是模拟一次“查看者”的合法请求。

我拆过这套流程,核心链路分三步。第一步,用你的QQ号登录态换取一个访问令牌,这个令牌相当于你作为查看者的“工牌”。第二步,构造一个查询请求,目标地址是QQ群相关的资料接口,请求头里带上被查QQ号、你的令牌、以及一个标识查看场景的字段。第三步,接口返回JSON或类JSON的结构化数据,脚本解析后落成表格。这里最关键的参数是bkn或g_tk这类由登录Cookie派生出的校验值——它是QQ接口防跨站请求伪造的机制,和Cookie中的skey有固定的换算关系。脚本里那几行看起来不起眼的位运算,干的就是这件事。

为什么选Web接口而不是直接Hook本地客户端?我在模拟项目X里两种都试过。Hook客户端的优点是没有接口权限限制,但缺点极其明显:每个客户端版本都要重新适配逆向,一旦QQ升级,整个脚本就废了一半;而且Hook过程容易触发本机安全软件的警告,运行环境非常挑机器。Web接口方案虽然拿不到非公开的群,但它稳定、可解释、代码量少,适合作为长期维护的工具。我更推荐后者,尤其是当你要处理几十个QQ号批量查询时,Web接口的请求频率是可控的,而Hook方案根本撑不住并发。

2.2 协议版本与Cookie依赖:这脚本不是“开箱即用”的捞群工具

需要给新手泼一盆冷水:这个脚本不是装上就能跑,它依赖你手动提供一份“登录态”。所谓登录态,就是你在浏览器里登录QQ后,浏览器Cookie里那几个特定字段的值。脚本读取这些值,才能伪装成你本人去发起查询。常见的字段组合是uin(你的QQ号)、skey(会话密钥)、p_skey(部分接口的独立密钥)。注意,skey和p_skey的有效期差异很大,有的几小时就失效,有的能撑一周。

从工程角度看,这其实是个可接受的权衡。让用户自己从浏览器复制Cookie,虽然步骤繁琐,但避免了在脚本里硬编码账号密码带来的更大安全隐患。毕竟如果工具内置了登录功能,那它就成了一个潜在的账密收集器,这在合规上完全是另一回事。所以脚本设计者选择了“半自动”模式:登录靠你手动完成,查询靠脚本自动化。这个边界划得是对的。

在实际复现时,你会发现查找Cookie的过程比想象中花时间。不同浏览器对Cookie的显示方式不一样,Chrome的Application面板和Firefox的Storage面板路径完全不同。我一般会建议先登录一个QQ相关的Web页面(比如QQ空间或QQ邮箱),然后通过开发者工具筛选qzone.qq.com或mail.qq.com域下的Cookie。为什么是这两个域名?因为它们返回的Cookie集合最完整,能覆盖脚本里用到的所有字段。如果你从其他站点抓,可能缺p_skey,脚本就会在第二步报错。

2.3 核心依赖选型:requests加json就够,别引入重型框架

看脚本的依赖清单,其实非常克制:核心是requests,加标准库里的re、json、time。没有用Scrapy,也没有用Selenium,因为这是个轻量级查询脚本,不是爬虫框架。requests负责维持会话和发送HTTP请求,re用来从HTML里抽取出bkn的生成参数,json做响应解析,time控制请求间隔。这个选型很聪明——如果你用Selenium去无头浏览器驱动页面,光是启动浏览器的开销就是接口直连的十几倍,而且更容易被风控识别。

这里有个容易被忽略的细节:脚本里用一个requests.Session()对象而不是每次直接requests.get()。原因是Cookie和Headers需要在整个会话中保持一致。Session对象会自动管理响应头里的set-cookie,省去手动拼接字符串的麻烦。我在某图像处理Demo里也习惯这么做,它能保证后续请求携带前一次请求种下的Cookie,避免因Cookie缺失导致的“未登录”错误。

依赖安装建议用虚拟环境,避免污染全局Python。创建环境、安装依赖、运行脚本这条路,走的次数多了就会形成肌肉记忆。下面这段是环境准备的标准操作:

# 创建并激活虚拟环境(Windows用venv,Linux/macOS用source激活) python -m venv qq_env qq_env/Scripts/activate # Windows # source qq_env/bin/activate # Linux/macOS # 安装依赖 pip install requests # 查看脚本入口,确认文件结构 python get_group_list.py --help

参数说明:--help不是必须的,但首次运行时它能打印脚本支持的命令行参数,比如目标QQ号、Cookie文件路径、输出格式等。这些参数的具体名称在不同版本的脚本里可能有差异,以实际代码里的argparse定义为准。虚拟环境的好处是不需要权限就能装包,而且后续卸载直接删目录,不留残余。

3. 实操复现:配置、跑通与参数调整

3.1 环境准备:从复制Cookie到写出第一份群列表

跑通的第一步永远是先把登录态准备好。打开浏览器,用你的主账号登录QQ空间,然后按F12打开开发者工具,切到Application(部分浏览器叫Storage)面板,左侧找到Cookies,展开当前站点域名,逐个查找并复制这些字段的值:uin、skey、p_skey。注意值的格式:uin通常是o123456这种带前导字母的字符串,skey和p_skey是一长串大小写混合的字符,复制时不要带引号和分号。

脚本读取Cookie的方式一般有两种:直接写在脚本开头的字典变量里,或者从一个文本文件加载。我更建议用文本文件,因为每次失效后只需要改文件,不用打开脚本源码。常见做法是在脚本同目录下建一个cookie.txt,每行一个字段,格式如下:

uin=o123456789 skey=xxxxxxxxxxxxxxxxxxxxxxxx p_skey=yyyyyyyyyyyyyyyyyyyy

然后运行脚本时,让它读取这个文件。举个具体调用示例:

python get_group_list.py --qq 654321 --cookie cookie.txt --output groups.csv

这里的--qq指定要查询的目标QQ号,--cookie指定登录态文件路径,--output指定结果导出路径。脚本会依次完成令牌计算、请求拼接、响应解析,最终把每个群的名称、群号、成员数、你在该群的入群时间等字段写入CSV。CSV的好处是后续能直接拖进Excel或Pandas做进一步分析,不需要额外转换。

跑通后你会看到终端输出类似这样的日志:

[信息] 正在计算bkn... [信息] bkn = 1234567890 [信息] 发送查询请求: https://xxxx.qq.com/... [信息] 获取到 3 个群组 [信息] 结果已保存到 groups.csv

如果只看到获取到 0 个群组,不一定是脚本坏了,很可能是目标账号的群权限设置为不公开,或者你当前的登录态没有权限查看。这一点在下一章会展开讲。

3.2 核心代码解读:bkn计算与请求构造

脚本的关键代码就那么几十行,但每一行都值得细看。下面是我从模拟项目X里还原出的核心片段,注释已经标了逻辑:

import requests, re, time, json def get_bkn(skey: str) -> str: """ 根据skey计算bkn(也叫g_tk)。 这是QQ接口防止跨站请求伪造的散列值, 算法固定:对skey逐字符ASCII码累加并与固定值做位运算。 """ hash_val = 5381 for char in skey: hash_val += (hash_val << 5) + ord(char) return str(hash_val & 2147483647) def fetch_group_list(qq: str, cookie_dict: dict) -> list: session = requests.Session() session.cookies.update(cookie_dict) skey = cookie_dict.get('skey', '') bkn = get_bkn(skey) # 这个URL是获取群列表的常用接口,实际以脚本内注释为准 url = 'https://qun.qq.com/cgi-bin/qun_mgr/get_group_list' params = { 'bkn': bkn, 'uin': qq, # 目标QQ号 'from': 'self', # 表示从个人资料卡发起 } headers = { 'Referer': 'https://qun.qq.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)', } resp = session.get(url, params=params, headers=headers, timeout=10) data = resp.json() if data.get('ec') != 0: raise RuntimeError(f"接口错误: {data.get('em')}") return data.get('data', {}).get('list', [])

这段代码的逻辑分三步。第一步是get_bkn函数,它接受skey字符串,按照固定的散列算法得到bkn,这个值必须作为查询参数传给接口,否则接口会直接拒绝。第二步是创建Session,把从文本文件读出的Cookie字典更新进会话,然后构造请求参数。第三步是发起GET请求,解析JSON。值得注意的是响应体里的ec字段,它是错误码,0表示成功,非零值会打印错误信息,这是排错的重要抓手。

参数说明里最需要调整的是from字段。有些版本的接口要求from='self',有些要求from='group',这取决于接口当时的版本。如果你返回的数据始终为空,试着改成from='other'或删除该参数,然后对比返回的JSON结构。我在某跨平台系统里调试时遇到过三次类似的情况,每次都是因为接口升级后参数名变动,改一下就能恢复。

另外,请求头里的Referer不能省略。QQ的接口会校验来源页,如果Referer不是QQ相关域名,会直接返回403。这是我第一次复现时踩的最深的坑——明明Cookie都齐全,却一直报权限错误,后来查了抓包日志才发现是Referer字段被脚本漏掉了。修复方法就是像上面代码里那样,显式声明Referer为https://qun.qq.com/。

3.3 参数调整与输出格式定制

脚本默认输出CSV,但我经常需要JSON格式,因为后续程序处理JSON更方便。如果你也遇到这个需求,可以直接在脚本末尾加一个参数判断:

# 在当前脚本的main函数里 import argparse def main(): parser = argparse.ArgumentParser() parser.add_argument('--qq', required=True) parser.add_argument('--cookie', required=True) parser.add_argument('--output', default='groups.csv') parser.add_argument('--format', choices=['csv', 'json'], default='csv') args = parser.parse_args() groups = fetch_group_list(args.qq, read_cookie(args.cookie)) if args.format == 'json': with open(args.output, 'w', encoding='utf-8') as f: json.dump(groups, f, ensure_ascii=False, indent=2) else: # 写CSV的逻辑,注意处理中文编码 import csv with open(args.output, 'w', newline='', encoding='utf-8-sig') as f: writer = csv.DictWriter(f, fieldnames=['name', 'gc', 'member_count', 'join_time']) writer.writeheader() for g in groups: writer.writerow(g)

这段扩展代码里,--format参数控制输出结构。写CSV时用utf-8-sig编码而不是utf-8,这是为了在Excel里打开时中文不乱码——UTF-8无BOM在Excel里会把第一个中文字段名显示成乱码,这个问题折磨过我很多次。如果输出文件还要给其他Python程序读取,那用JSON格式更稳妥,因为它保留了完整的嵌套结构。

请求间隔是另一个需要调整的参数。如果脚本需要查询多个QQ号,建议在每次请求之间加time.sleep(1),或者至少间隔0.5秒。不加间隔的后果是:短时间内请求次数过多,接口会返回一个ec=1202之类的风控错误码。间隔设置多长合适?我一般会在夜间批量查询时设成1.5秒,白天设成2秒,因为白天接口负载可能更高。这个值没有统一标准,以你的实际运行环境为准,原则是宁慢勿快。

4. 避坑指南:登录态过期、风控拦截、空数据是三大常见坑

4.1 现象:运行时报“token失效”或“请重新登录”

这是最常见的失败场景。你按照教程复制了Cookie,跑得正欢,突然脚本开始报错,提示登录态无效或bkn计算错误。我第一次遇到时还以为是代码写错了,排查了半天才发现是skey早就过期了。

原因:skey的过期时间由服务端动态决定,短则几十分钟,长则几天。影响因素包括你登录后的活跃度、IP地址是否变化、是否频繁切换User-Agent。更隐蔽的是,p_skey的过期时间往往比skey更短,部分接口只校验p_skey,如果你从Cookie里漏了这个字段,查询会失败但错误信息可能仍指向skey。

解决:没有自动化根治办法,只能重新打开浏览器登录一次QQ空间,刷新Cookie。我个人的习惯是写一个refresh_cookie.txt的占位文件,每次重新登录后把新Cookie粘贴进去。为了减少烦恼,建议不要用手机端验证码登录,而是用密码加扫码的混合方式,这样Cookie有效期通常更长。如果你发现每次只能稳定跑十几分钟就失效,那大概率是你的IP出口频繁切换(比如用了代理池),保持同一IP段就可以延长有效时间。

4.2 现象:高频请求触发风控,返回错误码1202

当你批量查询几百个QQ号时,脚本可能在连续运行五分钟后突然大面积报错,错误码通常是1202或-902,提示“操作过于频繁”。这本质上是接口的风控策略在起作用。

原因:短时间内在同一IP下发起了太多带相同登录态的请求,服务端认为是异常自动化行为。这里要说明的是,风控不是针对你的IP,而是针对“账号+IP”的组合。所以换IP无效,换账号也没用,只有降低频率才是正解。

解决:给每次请求加抖动延时,而不是固定间隔。固定间隔会被模式识别,抖动间隔能模拟人类操作。代码可以这么写:

import random, time, requests def safe_request(url, params, headers, session): # 每次请求前随机等待1.5到3秒 time.sleep(random.uniform(1.5, 3.0)) resp = session.get(url, params=params, headers=headers, timeout=10) if resp.json().get('ec') == 1202: # 遇到风控,额外等待10秒再重试一次 time.sleep(10) resp = session.get(url, params=params, headers=headers, timeout=10) return resp

参数说明:random.uniform(1.5, 3.0)生成一个1.5到3秒之间的随机浮点数,模拟人工操作的自然间隔。遇到风控时额外等待10秒,这是给服务端的限流窗口一个恢复时间。如果重试后仍然报1202,我建议直接停止脚本,等半小时再继续。血泪经验是:不要用无限循环去重试,这会加重账号的风控等级,甚至导致登录态被临时封禁。

4.3 现象:请求成功但返回0个群,数据去哪了

比报错更让人困惑的是接口返回正常,ec=0,但群列表是空的。你可能会怀疑目标QQ号是不是真的没加群,但大多数时候是权限问题。

原因:QQ的群列表可见性受对方设置控制。如果目标QQ号开启了“不允许通过资料卡查看我的群聊”,那么即使用接口查询,返回的群里也只包含“你们共同在的群”或者“对方设为公开的群”。这个设计本身是为了隐私保护,不是接口漏洞。另外,如果目标QQ号是你的好友,可见的群会多一些;如果不是好友,能看到的基本就是对方公开的群信息。

解决:在脚本里增加一个权限判断提示。当返回列表为空时,打印一个更清晰的提示,而不是直接输出空结果:

# 在fetch_group_list拿到data后 if 'list' not in data or not data['list']: print("[警告] 返回为空:可能对方设置了群列表不可见,或当前登录态权限不足") return []

这个提示能让使用者在数据为空时先检查权限,而不是反复调整接口参数。我在某次给某公司做的账号分析里,就因为没加这个提示,走了好几轮弯路,最后发现目标账号的群列表设了所有人都不可见。从那以后,我每次改写这类脚本都会强制在“空数据”路径上加日志输出,这是排错效率提升最大的一步。

4.4 现象:Cookie文件编码问题导致中文乱码或解析失败

另一个容易被忽略的坑是Cookie文件的编码。很多人在Windows上把Cookie复制到记事本里保存,默认会存成带BOM的UTF-8格式。脚本读取时如果用utf-8解码,可能会在第一个字段名里混入隐藏字符\ufeff,导致字段解析失败,报KeyError。

解决:在读取Cookie时用utf-8-sig编码,或者读取后做一次清洗。代码示例:

def read_cookie(path): with open(path, 'r', encoding='utf-8-sig') as f: content = f.read() cookie_dict = {} for line in content.strip().splitlines(): if '=' in line: key, value = line.split('=', 1) cookie_dict[key.strip()] = value.strip() return cookie_dict

参数说明:utf-8-sig会自动剥离文件开头的BOM,避免\ufeff污染第一个键名。split('=', 1)保证值里如果有等号也不会被截断。这个函数比直接dict(line.split())更鲁棒。如果你发现之前用其他脚本读Cookie偶尔失败,多半就是编码问题,换成这种方式后基本不会再犯。

5. 更进一步:把群列表变成可用情报的三种玩法

拿到CSV只是第一步,真正的价值在后续分析。根据我跑过的账号梳理项目,有三种玩法最实用。

第一种是群活跃度交叉分析。把拿到的群列表和你在每个群的发言次数(可以从QQ聊天记录导出)做交集,能快速找出那些“加了但从不说话”的僵尸群,以及“没怎么发言但群人数很多”的高潜群。具体操作是:用Pandas把CSV读进来,按照群的群号(gc字段)和你的本地聊天记录做外连接,然后按成员数排序,筛选出大于500人的群,再标记你是否在最近30天内发过言。这样一张表就能支撑账号清理或运营触达决策。

第二种是群归属网络可视化。把多个QQ号的群列表合并,用NetworkX建图:节点是群,节点大小是成员数,颜色是群分类;两个QQ号共属的群之间连一条边。这种图能很直观地看出不同账号之间的社交重叠度。我在某实验室的项目里就用这种方法找到了多个账号共享的“核心枢纽群”,省去了逐一搜索的麻烦。核心代码不复杂,用csv.DictReader读取多个文件,然后用字典统计群号出现的频率。

第三种是定时变更监控。把群列表脚本写成定时任务,每天凌晨跑一次,记录每次的群数量和群名快照。对比昨天和今天的CSV,就能自动发现“目标账号新加入了哪些群”“哪些群被解散了”之类的动态变化。这个玩法特别适合账号归属权变动的场景——当某个人突然退出或加入一个关键群,时间戳会直接暴露线索。脚本层面只需加一个--snapshot-dir参数,把每次输出按日期归档,再用diff或者Python的set操作对比群号集合。

这三条路最终都指向同一个习惯:不要只跑脚本存个CSV就完事,而是把每一次查询结果当成可追溯的数据快照。我现在的做法是每次跑批都强制走一遍“读取Cookie→请求→输出带时间戳文件→自动做差异对比”的完整流程,落地成一个10分钟能完成的标准动作。希望这篇拆解帮你在拿到脚本后少走几趟弯路,真正把群列表变成你手上的有效资产。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 17:59:43

UE5 C++字符串与容器全解析:FString、FName、FText与TArray、TMap底层原理

做 UE5 C 开发&#xff0c;容器和字符串这两块绕不过去。项目做大了&#xff0c;每次新建一个类、存一份配置、调一次接口&#xff0c;都要跟它们打交道。我最早是从 std 那套东西切过来的&#xff0c;一开始真被 UE 的命名搞晕过——明明都是字符串&#xff0c;为什么有 FStri…

作者头像 李华
网站建设 2026/10/18 17:55:09

Kafka跨集群同步方案全解析:从MirrorMaker 2.0到自研管道的选型指南

最近大半年&#xff0c;我陆续被拉进好几个项目&#xff0c;需求听起来都差不多&#xff1a;把Kafka里的数据同步到另一套Kafka。有的要跨机房灾备&#xff0c;源集群挂了备份集群能立刻顶上&#xff1b;有的是老集群退役&#xff0c;几千个topic要原样搬去新集群&#xff1b;还…

作者头像 李华
网站建设 2026/10/18 17:54:32

机动车合格证PDF417二维码解码实战:从图像预处理到字段解析

简介&#xff1a;这份资源面向机动车管理、保险车贷录单及车辆库存管理等场景的开发者&#xff0c;提供一套基于Python的机动车合格证二维码解码实现方案&#xff0c;可快速提取车架号、发动机号、品牌与车型等关键信息&#xff0c;解决手工录入效率低、易出错的问题。压缩包共…

作者头像 李华
网站建设 2026/10/18 17:51:28

AI辅助教材写作技巧与低查重方法全攻略

写教材这件事&#xff0c;不少老师都觉得是“费力不讨好”的苦差事&#xff1a;内容体系要严谨、风格要统一、案例要贴合教学、进度还得赶得上。近几年AI工具确实给这个领域带来了不小的变化&#xff0c;我身边陆续有同事开始摸索用AI辅助教材编写&#xff0c;但真正能用顺手的…

作者头像 李华
网站建设 2026/10/18 17:50:45

EXE反编译为VB源码:P-Code与Native Code还原度全解析

简介&#xff1a;这是一款基于VB6开发的EXE反编译工具&#xff0c;目标用户为VB6开发者、软件逆向与分析爱好者。它能够将已编译的EXE文件转换回VB源代码&#xff0c;帮助使用者了解他人程序的运行逻辑、学习编程技巧&#xff0c;或用于合法的逆向工程。资源包共30个文件&#…

作者头像 李华