校园招新之获取进QQ群但未报名人员

校园的社团、实验室招新一般由是校领导会发一个QQ通知,让各个班的同学们进一个招新群。 群里面会有负责人提示大家报名,但是群成员不总是都会报名,我们需要的就是,找到那些,已经进群,但是没有报名的同学,然后私聊提醒一下。

大体思路:获取QQ群成员列表,获取已经报名的人员(从问卷星导出,使用go读取execl),根据两者(我们使用QQ群昵称 “计科203张三” 和 execl中的班级+姓名作为判断标准)即可求出我们想要的差集合并集。  

获取QQ群成员列表

参考文章:js解密之QQ的bkn值,获取QQ群成员信息,获取QQ好友列表信息-腾讯云开发者社区-腾讯云

 进入网站:https://qun.qq.com/member.html 登录,选择群,打开网络请求

解析参数:

  • gc,应该是群id
  • st: 开始下标 
  • end :结束下标
  • sort:不知道
  • bkn:加密用的应该是

解析response

  •  adm_num :管理员数量,不带群主
  • count: 群成员总数
  • mems : 群成员列表
  • mems.role : 0是群主,1是管理员,2是群成员
  • card: 群昵称

nick:QQ昵称

 使用网络抓包即可,导入apifox即可

 具体代码

package main

import (
	"encoding/json"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

type QQUser struct {
	Uin           int `json:"uin"`
	Role          int `json:"role"`
	G             int `json:"g"`
	JoinTime      int `json:"join_time"`
	LastSpeakTime int `json:"last_speak_time"`
	Lv            struct {
		Point int `json:"point"`
		Level int `json:"level"`
	} `json:"lv"`
	Card string `json:"card"`
	Tags string `json:"tags"`
	Flag int    `json:"flag"`
	Nick string `json:"nick"`
	Qage int    `json:"qage"`
	Rm   int    `json:"rm"`
}
type JSONData struct {
	Ec          int         `json:"ec"`
	Errcode     int         `json:"errcode"`
	Em          string      `json:"em"`
	Cache       int         `json:"cache"`
	AdmNum      int         `json:"adm_num"`
	Levelname   interface{} `json:"levelname"`
	Mems        []QQUser    `json:"mems"`
	Count       int         `json:"count"`
	SvrTime     int         `json:"svr_time"`
	MaxCount    int         `json:"max_count"`
	SearchCount int         `json:"search_count"`
	Extmode     int         `json:"extmode"`
}
type WJXUser struct {
	Class string
	Name  string
}

func ReadExcel(filename string) (RegisteredUserList []WJXUser, err error) {
	f, err := excelize.OpenFile(filename)
	if err != nil {
		return
	}
	sheets := f.GetSheetMap() //获取Execl表的工作表
	fmt.Println(sheets)
	sheet1 := sheets[1] //sheets是一个map,map[1]就是获取到第一个工作表
	fmt.Println("第一个工作表", sheet1)
	rows := f.GetRows(sheet1) //获取工作表的所有数据,数据存储在一个二维数组中,二维数组中的每一个一位数组就是一行数据
	fmt.Println(rows)
	RegisteredUserList = make([]WJXUser, 0)
	for i := 1; i < len(rows); i++ {
		name := strings.ReplaceAll(rows[i][6], " ", "")
		name = strings.ReplaceAll(name, "&nbsp;", "")
		class := strings.ReplaceAll(rows[i][9], " ", "")
		class = strings.ReplaceAll(class, "&nbsp;", "")
		class = strings.ReplaceAll(class, "班", "")
		RegisteredUser := WJXUser{Name: name, Class: class}
		RegisteredUserList = append(RegisteredUserList, RegisteredUser)
	}
	return RegisteredUserList, err
}
func main() {
	url := "https://qun.qq.com/cgi-bin/qun_mgr/search_group_members"
	method := "POST"
	client := &http.Client{}
	NotedUserList := make([]QQUser, 0)  // 已经进QQ群且已经备注人员 (已经剔除管理员)
	NoNoteUserList := make([]QQUser, 0) // 已经进QQ群但是未备注人员(已经剔除管理员)
	countMember := 0                    // 群成员总数量
	cycleIndex := 1                     // 刚开始让循环一轮,后面根据群成员总数来确定到底循环多少轮
	for i := 0; i < cycleIndex; i++ {
		st := i * 21
		end := st + 20
		if i != 0 && i == cycleIndex-1 { // For the fifth iteration, set the end to 86
			end = countMember
		}
		payload := strings.NewReader(fmt.Sprintf("gc=185335516&st=%d&end=%d&sort=0&bkn=336337277", st, end))
		req, err := http.NewRequest(method, url, payload)
		if err != nil {
			return
		}
		req.Header.Add("Accept", "application/json, text/javascript, */*; q=0.01")
		req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9")
		req.Header.Add("Connection", "keep-alive")
		req.Header.Add("Origin", "https://qun.qq.com")
		req.Header.Add("Referer", "https://qun.qq.com/member.html")
		req.Header.Add("Sec-Fetch-Dest", "empty")
		req.Header.Add("Sec-Fetch-Mode", "cors")
		req.Header.Add("Sec-Fetch-Site", "same-origin")
		req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36")
		req.Header.Add("X-Requested-With", "XMLHttpRequest")
		req.Header.Add("sec-ch-ua", "\"Google Chrome\";v=\"125\", \"Chromium\";v=\"125\", \"Not.A/Brand\";v=\"24\"")
		req.Header.Add("sec-ch-ua-mobile", "?0")
		req.Header.Add("sec-ch-ua-platform", "\"macOS\"")
		req.Header.Add("Cookie", "RK=Gdv1uMjH8g; ptcz=cc0188ccc671556dd56ea8ffb4ae59d282714e8e788826033f41c89d77b61b53; pgv_pvid=4845315920; tgw_l7_route=9d1d4698c4322116c7c255687ec1fe38; traceid=cfd4c1d7fb; uin=o3063360183; skey=@61HarNEbA; p_uin=o3063360183; pt4_token=e6WELkURyGZz0yu3RI3j1UwIQk5z9E7n9dUrbXmq4gE_; p_skey=GQ0pK0oDZsKCwOphrmWqZtFoCE5qsUVEqZfgDLHn7FU_")
		req.Header.Add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
		req.Header.Add("Host", "qun.qq.com")
		res, err := client.Do(req)
		if err != nil {
			fmt.Println(err)
			return
		}
		defer res.Body.Close()

		body, err := ioutil.ReadAll(res.Body)
		if err != nil {
			fmt.Println(err)
			return
		}

		var r JSONData
		err = json.Unmarshal(body, &r)
		countMember = r.Count
		cycleIndex = countMember/21 + 1 // 每次查询是21人,不足21次的向上取整一下
		if err != nil {
			fmt.Println("Error unmarshalling response:", err)
			return
		}
		for j := 0; j < len(r.Mems); j++ {
			if r.Mems[j].Role == 2 {
				if r.Mems[j].Card == "" {
					NoNoteUserList = append(NoNoteUserList, r.Mems[j])
				} else {
					// 数据处理,让数据保持格式为 “计科221张三”
					r.Mems[j].Card = strings.ReplaceAll(r.Mems[j].Card, " ", "")
					r.Mems[j].Card = strings.ReplaceAll(r.Mems[j].Card, "&nbsp;", "")
					r.Mems[j].Card = strings.ReplaceAll(r.Mems[j].Card, "班", "")
					NotedUserList = append(NotedUserList, r.Mems[j])
				}

			}
		}
		time.Sleep(2 * time.Second)
	}
	registeredUserList, err := ReadExcel("/Users/yjppjy/Downloads/263778738_按序号_π-Team报名表_54_51.xlsx") // 已经报名人员
	if err != nil {
		return
	}
	// 根据 NoteUserList中的.Card字段 和 registeredUserList的 Class + Name 作为判断依据,以QQUser为基准,找出来 未进群但是已报名、已进群已报名、已进群未报名的人员
	// 将已报名人员存储在一个map中,以便快速查找
	registeredUserMap := make(map[string]WJXUser)
	for _, user := range registeredUserList {
		key := user.Class + user.Name
		registeredUserMap[key] = user
	}

	// 查找已进群已报名、已进群未报名
	var notedAndRegistered []QQUser
	var notedAndNotRegistered []QQUser

	for _, qqUser := range NotedUserList {
		key := qqUser.Card
		if _, found := registeredUserMap[key]; found {
			notedAndRegistered = append(notedAndRegistered, qqUser)
		} else {
			notedAndNotRegistered = append(notedAndNotRegistered, qqUser)
		}
	}

	// 查找未进群但已报名
	var notInGroupButRegistered []WJXUser
	for key, wjxUser := range registeredUserMap {
		found := false
		for _, qqUser := range NotedUserList {
			if qqUser.Card == key {
				found = true
				break
			}
		}
		if !found {
			notInGroupButRegistered = append(notInGroupButRegistered, wjxUser)
		}
	}

	// 输出结果
	//fmt.Println("已进群已报名:")
	//for _, user := range notedAndRegistered {
	//	fmt.Println(user.Card, user.Nick)
	//}

	fmt.Println("已进群未报名:")
	for _, user := range notedAndNotRegistered {
		fmt.Println(user.Card, user.Nick)
	}

	fmt.Println("未进群但已报名:")
	for _, user := range notInGroupButRegistered {
		fmt.Println(user.Class, user.Name)
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/644639.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络原理 一

一、协议 网络通信中,协议是非常重要的概念. 协议进行了分层,此处就是按照这几层顺序来介绍每一层中的核心协议. 应用层,就对应着应用程序,是程序员打交道最多的一层,调用系统提供的 网络api 写出的代码都是基于应用层的. 应用层这里当然也有很多现成的协议,但更多的还是,程…

mysql实战——XtraBackup二进制包安装

1、二进制包下载网站 Software Downloads - Percona 2、安装xtrabackup 解压安装包 tar xvf percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17.tar.gz -C /usr/local 进入目录 cd percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17/ 安装依赖 yum install perl-Dig…

游戏子弹类python设计与实现详解

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、子弹类设计思路 1. 属性定义 2. 方法设计 三、子弹类实现详解 1. 定义子弹…

SimLab Composer v11.0.46 解锁版安装教程 (3D设计和逼真场景的多功能软件)

前言 SimLab Composer是由Simulation Lab公司推出的一款用于3D设计和逼真场景的多功能软件。该程序具有集成的图形环境&#xff0c;用于真实设计物理场景和对象&#xff0c;用户可以使用该软件中的工具设计简单到复杂和复杂。该程序的一个重要功能是能够构建和共享三维pdf文件…

揭秘章子怡成功之路:她是如何征服世界的?

章子怡的演艺生涯可谓是一部传奇❗❗❗ 从一个普通工人家庭的女孩&#xff0c;到如今的国际巨星 她的每一步都充满了努力和汗水 她的舞蹈基础为她日后的演艺事业奠定了坚实的基础 而她对戏剧和电影的热爱更是让她在演艺道路上不断前行 从《我的父亲母亲》到《卧虎藏龙》&…

【CTF Web】CTFShow web5 Writeup(SQL注入+PHP+位运算)

web5 1 阿呆被老板狂骂一通&#xff0c;决定改掉自己大意的毛病&#xff0c;痛下杀手&#xff0c;修补漏洞。 解法 注意到&#xff1a; <!-- flag in id 1000 -->拦截很多种字符&#xff0c;连 select 也不给用了。 if(preg_match("/\|\"|or|\||\-|\\\|\/|\…

Linux程序开发(十二):线程与多线程同步互斥实现抢票系统

Tips&#xff1a;"分享是快乐的源泉&#x1f4a7;&#xff0c;在我的博客里&#xff0c;不仅有知识的海洋&#x1f30a;&#xff0c;还有满满的正能量加持&#x1f4aa;&#xff0c;快来和我一起分享这份快乐吧&#x1f60a;&#xff01; 喜欢我的博客的话&#xff0c;记得…

window好用的网速工具

这是一个用于显示当前网速、CPU及内存利用率的桌面悬浮窗软件&#xff0c;并支持任务栏显示&#xff0c;支持更换皮肤。 github链接如下 https://github.com/zhongyang219/TrafficMonitor?tabreadme-ov-file

单窗口一天收益30+ 最新海外炼游地铁跑酷全自动黑科技项目,【软件+使用教程】

随着游戏界的最新狂潮&#xff0c;一款名为“海外酷跑”的游戏引起了全球玩家的关注。它继承了经典的地铁酷跑的精髓&#xff0c;同时注入了一种全新的元素&#xff1a;金币兑换虚拟货币的功能。玩家能够通过积极参与游戏、收集金币来兑换虚拟代币&#xff0c;每达到98000金币就…

详细分析Element中的MessageBox基本知识(附Demo)

目录 前言1. 基本知识2. Demo2.1 确认框2.2 警告框2.3 对话框 3. this.$confirm 前言 详细知识推荐阅读&#xff1a;详细分析Element Plus中的ElMessageBox弹窗用法&#xff08;附Demo及模版&#xff09; MessageBox则常用于Vue2 1. 基本知识 MessageBox 是 Element UI 提供…

每日一题——博弈论(枚举与暴力)

博弈论 题目描述 运行代码 #include<iostream> #include<vector> using namespace std; int main(){int n;cin >> n;vector<int> d(n,0);for(int i 0;i < n;i){cin >> d[i];}vector<int> in(1000,0);for(int k 1;k<3;k){for(int…

SpringBoot 集成 Nebula

工作需求&#xff0c;开始了解图数据库&#xff0c;经过工具选型&#xff0c;最终选择nebula graph&#xff0c;并集成到springboot&#xff0c;java 环境下如何对 Nebula Graph 进行操作&#xff0c;本文整理下过程。 1、首先引入 pom 依赖 <dependency><groupId&g…

【vue】el-select选择器实现宽度自适应

选择器的宽度根据内容长度进行变化 <div class"Space_content"><el-selectv-model"value":placeholder"$t(bot.roommessage)"class"select"size"small"style"margin-right: 10px"change"selectcha…

上5个B端系统的设计规范,让你的开发比着葫芦画瓢。

B端系统设计规范在企业级系统开发中起着重要的作用&#xff0c;具体包括以下几个方面&#xff1a; 统一风格和布局&#xff1a;设计规范能够统一系统的风格和布局&#xff0c;使不同功能模块的界面看起来一致&#xff0c;提升用户的使用体验和学习成本。通过统一的设计规范&am…

AI应用案例:影像报告智能辅助编辑系统

今天给大家介绍一个医疗行业的案例“影像报告智能辅助编辑系统”&#xff01;该案例已经在某三甲医院落地&#xff0c;模型准确度超过80%。 该项目上线后&#xff0c;保守估计&#xff0c;能为每位医生的每一张报告至少省下1分钟时间和2分钟的精力&#xff0c;20位初级医生&…

APP安全测试汇总【网络安全】

APP安全测试汇总 一.安装包签名和证书 1.问题说明 检测 APP 移动客户端是否经过了正确签名&#xff0c;通过检测签名&#xff0c;可以检测出安装包在签名后是否被修改过。如 果 APP 使⽤了 debug 进⾏证书签名&#xff0c;那么 APP 中⼀部分 signature 级别的权限控制就会失效…

材料物理 笔记-9

原内容请参考哈尔滨工业大学何飞教授&#xff1a;https://www.bilibili.com/video/BV18b4y1Y7wd/?p12&spm_id_frompageDriver&vd_source61654d4a6e8d7941436149dd99026962 或《材料物理性能及其在材料研究中的应用》&#xff08;哈尔滨工业大学出版社&#xff09; ——…

【C++练级之路】【Lv.21】C++11——列表初始化和声明

快乐的流畅&#xff1a;个人主页 个人专栏&#xff1a;《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火&#xff0c;在为久候之人燃烧&#xff01; 文章目录 引言一、列表初始化1.1 内置类型1.2 结构体或类1.3 容器 二、声明2.1 auto2.2 decltype2.3 nullptr 三、STL的…

8个图神经网络的典型用例

虽然 ChatGPT 或 Diffusion 模型等 AI 系统最近备受关注&#xff0c;但图神经网络 (GNN) 却发展迅速。在过去的几年中&#xff0c;GNN 悄然成为众多激动人心的新成就背后的黑马&#xff0c;这些成就从纯学术研究突破一路发展到大规模积极部署的实际解决方案。 Uber、谷歌、阿里…

一文讲解——Java多态

目录 一、什么是多态&#xff1f;二、转型向上转型向下转型 三、方法覆盖与方法重载四、绑定动态绑定静态绑定 五、理解多态 一、什么是多态&#xff1f; 多态的词组字面意思是&#xff1a; 某种事物多种形态。 但是对于我们学习Java 的程序原来说&#xff0c;就不不能简单这样…