ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

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

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用venvLinux/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每行一个字段格式如下uino123456789 skeyxxxxxxxxxxxxxxxxxxxxxxxx p_skeyyyyyyyyyyyyyyyyyyyyy然后运行脚本时让它读取这个文件。举个具体调用示例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, paramsparams, headersheaders, timeout10) 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字段。有些版本的接口要求fromself有些要求fromgroup这取决于接口当时的版本。如果你返回的数据始终为空试着改成fromother或删除该参数然后对比返回的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, requiredTrue) parser.add_argument(--cookie, requiredTrue) parser.add_argument(--output, defaultgroups.csv) parser.add_argument(--format, choices[csv, json], defaultcsv) args parser.parse_args() groups fetch_group_list(args.qq, read_cookie(args.cookie)) if args.format json: with open(args.output, w, encodingutf-8) as f: json.dump(groups, f, ensure_asciiFalse, indent2) else: # 写CSV的逻辑注意处理中文编码 import csv with open(args.output, w, newline, encodingutf-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秒。不加间隔的后果是短时间内请求次数过多接口会返回一个ec1202之类的风控错误码。间隔设置多长合适我一般会在夜间批量查询时设成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, paramsparams, headersheaders, timeout10) if resp.json().get(ec) 1202: # 遇到风控额外等待10秒再重试一次 time.sleep(10) resp session.get(url, paramsparams, headersheaders, timeout10) return resp参数说明random.uniform(1.5, 3.0)生成一个1.5到3秒之间的随机浮点数模拟人工操作的自然间隔。遇到风控时额外等待10秒这是给服务端的限流窗口一个恢复时间。如果重试后仍然报1202我建议直接停止脚本等半小时再继续。血泪经验是不要用无限循环去重试这会加重账号的风控等级甚至导致登录态被临时封禁。4.3 现象请求成功但返回0个群数据去哪了比报错更让人困惑的是接口返回正常ec0但群列表是空的。你可能会怀疑目标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, encodingutf-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分钟能完成的标准动作。希望这篇拆解帮你在拿到脚本后少走几趟弯路真正把群列表变成你手上的有效资产。本文还有配套的精品资源点击获取
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表