Skip to content

Instantly share code, notes, and snippets.

@bczhc
Last active March 10, 2026 03:07
Show Gist options
  • Select an option

  • Save bczhc/950f87e7e957de2ce72bfaad95a21778 to your computer and use it in GitHub Desktop.

Select an option

Save bczhc/950f87e7e957de2ce72bfaad95a21778 to your computer and use it in GitHub Desktop.
QQ获取共同群 #qq

使用onebot API。可以使用 https://github.com/LLOneBot/LuckyLilliaBot 方便导出。

qq-group-member-list输出为jsonl,每一行的类型定义为:

export interface Welcome {
    group_id:   number;
    group_data: GroupData;
    result:     Result;
}

export interface GroupData {
    group_id:              number;
    group_name:            string;
    group_memo:            string;
    group_create_time:     number;
    member_count:          number;
    max_member_count:      number;
    remark_name:           string;
    avatar_url:            string;
    owner_id:              number;
    is_top:                boolean;
    shut_up_all_timestamp: number;
    shut_up_me_timestamp:  number;
}

export interface Result {
    status:  string;
    retcode: number;
    data:    Datum[];
    message: string;
    wording: string;
}

export interface Datum {
    group_id:          number;
    user_id:           number;
    nickname:          string;
    card:              string;
    card_or_nickname:  string;
    sex:               string;
    age:               number;
    area:              string;
    level:             string;
    qq_level:          number;
    join_time:         number;
    last_sent_time:    number;
    title_expire_time: number;
    unfriendly:        boolean;
    card_changeable:   boolean;
    is_robot:          boolean;
    shut_up_timestamp: number;
    role:              string;
    title:             string;
}

common-qq-member进行聚合并打印。

#!/bin/env ruby
require 'json'
require 'json'
# 根据你的输入文件名
INPUT_FILE = "group-members.jsonl"
# 存储结构:
# user_map = {
# user_id => {
# nickname: "...",
# groups: [ {id: 123, name: "群A"}, {id: 456, name: "群B"} ]
# }
# }
user_map = Hash.new { |hash, key| hash[key] = { nickname: "", groups: [] } }
puts "正在读取 #{INPUT_FILE} 并分析共同成员..."
unless File.exist?(INPUT_FILE)
puts "错误:找不到文件 #{INPUT_FILE}"
exit 1
end
File.foreach(INPUT_FILE) do |line|
next if line.strip.empty?
begin
data = JSON.parse(line)
# 提取群组基础信息 (zzz 部分)
group_info = {
id: data["group_id"],
name: data.dig("group_data", "group_name") || "未知群名"
}
# 提取成员列表 (yyy 部分)
members = data.dig("result", "data") || []
members.each do |member|
uid = member["user_id"]
nick = member["nickname"]
# 更新昵称(以最后一次扫描到的为准)
user_map[uid][:nickname] = nick
# 记录该成员所在的群组信息
user_map[uid][:groups] << group_info
end
rescue JSON::ParserError
fail
end
end
# 过滤出加入群组数量 >= 2 的成员
common_members = user_map.select { |_, info| info[:groups].size >= 2 }
# 按群数量降序排列
sorted_members = common_members.sort_by { |_, info| -info[:groups].size }
puts "--- 共同成员详细报告 ---"
puts "发现共同成员数量: #{sorted_members.size}"
puts "-" * 60
sorted_members.each do |uid, info|
# 提取所有群名并用逗号连接
group_names = info[:groups].map { |g| "【#{g[:name]}】" }.join(", ")
next if uid == 1109236592 # 我
next if uid == 2854196310 # Q群管家
# next if group_names != '【XXX】, 【YYY】'
puts "用户ID: #{uid}"
puts "昵称 : #{info[:nickname]}"
puts "活跃在 : #{info[:groups].size} 个群"
puts "群名称 : #{group_names}"
puts "-" * 60
end
#!/bin/env ruby
require 'net/http'
require 'json'
require 'uri'
# 配置参数
BASE_URL = "http://localhost:3000"
OUTPUT_FILE = "group-members.jsonl"
def post_api(endpoint, params = {})
uri = URI("#{BASE_URL}#{endpoint}")
# 处理带有查询参数的 POST 请求
uri.query = URI.encode_www_form(params) unless params.empty?
response = Net::HTTP.post_form(uri, {})
data = JSON.parse(response.body)
# 严格检查状态,不为 ok 则退出
if data["status"] == "ok"
return data
else
puts "终止:接口 #{endpoint} 返回状态 [#{data["status"]}]。脚本已退出。"
exit 1
end
rescue => e
puts "网络请求异常: #{e.message}"
exit 1
end
# 1. 获取所有群组原始数据
puts "正在获取群组列表..."
all_groups_response = post_api("/get_group_list")
groups_list = all_groups_response["data"] # 这里包含完整的群组对象数组
puts "成功获取 #{groups_list.size} 个群组,准备导出成员数据..."
# 2. 遍历并合并数据写入文件
File.open(OUTPUT_FILE, "w") do |file|
groups_list.each_with_index do |group_obj, index|
gid = group_obj["group_id"]
puts "[#{index + 1}/#{groups_list.size}] 处理中: #{gid}"
# 请求该群的成员列表
member_response = post_api("/get_group_member_list", { group_id: gid })
# 构造复合 JSONL 行
line_data = {
"group_id" => gid,
"group_data" => group_obj, # zzz: 来自 /get_group_list 的原始对象
"result" => member_response # yyy: 来自 /get_group_member_list 的原始返回
}
file.puts(line_data.to_json)
# 频率控制,保护 API 稳定性
sleep(2)
end
end
puts "---"
puts "数据抓取完成!输出文件:#{OUTPUT_FILE}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment