导出群成员名单

导出 QQ 名单已确定哪些成员没有加群

  1. // ==UserScript==
  2. // @name 导出群成员名单
  3. // @namespace com.junwe.qgtool
  4. // @version 0.1
  5. // @description 导出 QQ 名单已确定哪些成员没有加群
  6. // @author jw23
  7. // @match https://qun.qq.com/*
  8. // @require https://cdn.jsdelivr.net/npm/papaparse@5.4.1/papaparse.min.js
  9. // @grant GM_xmlhttpRequest
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (async function () {
  14. 'use strict';
  15.  
  16. let buttonContainer = await waitUtil("._operationSection_1pula_8>div");
  17.  
  18. let btnWrapper = document.createElement("div");
  19. btnWrapper.className = "t-space-item";
  20. let btn = document.createElement("button");
  21. btn.textContent = "导出群成员"
  22. btn.className = "t-button t-button--theme-default t-button--variant-base";
  23. btnWrapper.appendChild(btn);
  24.  
  25. btn.onclick = async () => {
  26. let group_id = prompt("请输入群号");
  27. try {
  28. let mems = await colllectMemebers(parseInt(group_id));
  29. console.log(mems);
  30. let csv = Papa.unparse(mems)
  31. exportJsonFile(csv, `${group_id}-members.csv`);
  32. } catch (err) {
  33. console.log("抓取群成员失败: ", err);
  34. }
  35. }
  36. buttonContainer.appendChild(btnWrapper)
  37. })();
  38.  
  39. function getBkn() {
  40. let t = document.cookie.match(new RegExp(`(^| )skey=([^;]*)(;|$)`));
  41. let skey = t ? decodeURIComponent(t[2]) : "";
  42. let r_ = e => {
  43. let t = 5381;
  44. for (let n = 0, r = e.length; n < r; ++n)
  45. t += (t << 5) + e.charAt(n).charCodeAt(0);
  46. return String(t & 2147483647)
  47. }
  48. return r_(skey);
  49. }
  50. async function getMembers(group_id, start = 0, end = 9) {
  51. let bkn = getBkn();
  52. return new Promise((resolve, reject) => {
  53. GM_xmlhttpRequest({
  54. url: `https://qun.qq.com/cgi-bin/qun_mgr/search_group_members?bkn=${bkn}&ts=${Date.now()}`,
  55. method: "POST",
  56. headers: {
  57. "content-type": "application/x-www-form-urlencoded",
  58. "accept": "application/json, text/plain, */*",
  59. "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
  60. "Referer": "https://qun.qq.com/",
  61. "Referrer-Policy": "strict-origin-when-cross-origin"
  62. },
  63. data: `st=${start}&end=${end}&sort=1&gc=${group_id}&group_id=${group_id}&bkn=${bkn}`,
  64. onload: function (response) {
  65. console.log("Request successful!");
  66. let data = JSON.parse(response.responseText);
  67. resolve({ mems: data.mems, count: data.count });
  68. },
  69. onerror: function (response) {
  70. console.error("Request failed!");
  71. console.error("Response:", response);
  72. reject(response);
  73. },
  74. ontimeout: function (response) {
  75. console.error("Request timed out!");
  76. console.error("Response:", response);
  77. reject(response);
  78. }
  79. });
  80. })
  81. }
  82. async function waitUtil(cssSelector, timeout = 5000) {
  83. return new Promise((resolve, reject) => {
  84. let task = setTimeout(() => {
  85. let el = document.querySelector(cssSelector);
  86. if (el) {
  87. resolve(el);
  88. }
  89. }, 500)
  90. setTimeout(() => {
  91. clearInterval(task);
  92. resolve("timeout");
  93. }, timeout)
  94. })
  95. }
  96. async function colllectMemebers(group_id) {
  97. let start = 0;
  98. let step = 9
  99. let total = 200;
  100. let memebers = [];
  101. while (start <= total) {
  102. try {
  103. let { mems, count } = await getMembers(group_id, start, start + step);
  104. total = count;
  105. memebers.push(...mems);
  106. start += step;
  107. start++;
  108. } catch (err) {
  109. throw new Error("请求过程出现异常,请检查代码");
  110. }
  111.  
  112. }
  113. return memebers;
  114. }
  115. function exportJsonFile(data, filename = 'data.json') {
  116.  
  117. const blob = new Blob([data], { type: 'application/json' }); // 创建 Blob 对象
  118. const url = URL.createObjectURL(blob); // 创建 Blob URL
  119.  
  120. const downloadLink = document.createElement('a'); // 创建下载链接
  121. downloadLink.href = url;
  122. downloadLink.download = filename; // 设置下载文件名
  123. downloadLink.textContent = '下载 JSON 文件'; // 链接文本 (可选)
  124. downloadLink.style.display = 'none'; // 隐藏链接 (可选,可以设置为可见)
  125.  
  126. document.body.appendChild(downloadLink); // 将链接添加到文档 (必须添加到文档才能触发点击)
  127. downloadLink.click(); // 模拟点击下载链接
  128. document.body.removeChild(downloadLink); // 移除链接
  129.  
  130. URL.revokeObjectURL(url); // 释放 Blob URL (可选,但建议释放)
  131.  
  132. console.log(`JSON 文件 "${filename}" 导出成功!`);
  133. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址