GameMale
登陆 / 注册 搜索

USERCENTER

SEARCHSITE

搜索

查看: 1815|回复: 46
收起左侧

[功能优化] 【油猴脚本】积分记录一键统计

[复制链接] |关注本帖

咆哮虎的冠军之路裸体克里斯圣甲虫秘典永远的克叔【新春限定】果体 隆新神的赐福凯登‧阿兰科隐秘的讯息魂灵魔典炙热的格拉迪欧拉斯

     楼主| 星之子 发表于 4 天前 | 显示全部楼层 |阅读模式 <
    动机
    像试着统计一下自己究竟通过售卖附件获得了多少金币,就调教Gemini写了这个脚本。虽然最终效果不尽如人意,但由于是对“积分记录”这个页面的大部分选项都有效,或许还有一些我没想到过的用途。

    功能

    这个脚本在积分记录页面添加了一个“一键统计”按钮,选择好几个限制条件后点击一下,就可以统计出相关的条目数和总的积分变化。
    美中不足的是由于论坛限制,超过100页的部分获取不到,会显示“分页数不在允许的范围内”,按照每页20条计算,只能获取到前2000条。如果发帖很多、售卖附件获得金币的条目数也很多的话,就得自己控制时间范围,保证不超过2000条,否则脚本获取不全。
    关于对服务器可能造成的压力:脚本以每5页为一组进行抓取,每组之间休息500毫秒;且通过脚本获取的内容全部为文本格式。可以认为对服务器的压力不大。


    代码

    @Name  @Match  @Icon
    1. // ==UserScript==
    2. // @name         功能:GameMale积分记录一键统计
    3. // @namespace    http://tampermonkey.net/
    4. // @version      1.0
    5. // @description  引入并发控制与频率限制,保护服务器,防止触发封禁
    6. // @author       Gemini
    7. // @match        *://www.gamemale.com/home.php?mod=spacecp&ac=credit&op=log*
    8. // @grant        GM_xmlhttpRequest
    9. // ==/UserScript==

    10. (function() {
    11.     'use strict';

    12.     function parseHTML(html) { return new DOMParser().parseFromString(html, 'text/html'); }

    13.     function extractDataFromDoc(doc) {
    14.         let count = 0, sum = 0;
    15.         const rows = doc.querySelectorAll('table.dt tbody tr');
    16.         rows.forEach(row => {
    17.             const amountCell = row.querySelector('td:nth-child(2)');
    18.             if (amountCell) {
    19.                 const match = (amountCell.innerText || amountCell.textContent).match(/([-+]?\d+)/);
    20.                 if (match) {
    21.                     const value = parseInt(match[0], 10);
    22.                     if (!isNaN(value)) { sum += value; count++; }
    23.                 }
    24.             }
    25.         });
    26.         return { count, sum };
    27.     }

    28.     // 关键辅助函数:延时
    29.     const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));

    30.     function init() {
    31.         const form = document.querySelector('form[action*="home.php?mod=spacecp&ac=credit&op=log"]');
    32.         const searchBtn = form ? form.querySelector('button[name="search"]') : null;
    33.         if (!form || !searchBtn) return;

    34.         const calcBtn = document.createElement('button');
    35.         calcBtn.type = 'button';
    36.         calcBtn.className = 'pn';
    37.         calcBtn.style.marginLeft = '10px';
    38.         calcBtn.innerHTML = '<strong>一键统计</strong>';

    39.         const resultSpan = document.createElement('span');
    40.         resultSpan.style.marginLeft = '10px';
    41.         resultSpan.style.fontSize = '14px';

    42.         searchBtn.parentNode.insertBefore(calcBtn, searchBtn.nextSibling);
    43.         searchBtn.parentNode.insertBefore(resultSpan, calcBtn.nextSibling);

    44.         calcBtn.onclick = async function() {
    45.             resultSpan.innerHTML = '<span style="color:#999;">正在初始化...</span>';
    46.             calcBtn.disabled = true;

    47.             try {
    48.                 const formData = new FormData(form);
    49.                 const firstPageDoc = await new Promise((resolve, reject) => {
    50.                     GM_xmlhttpRequest({
    51.                         method: "POST",
    52.                         url: form.action,
    53.                         data: formData,
    54.                         onload: (res) => resolve(parseHTML(res.responseText)),
    55.                         onerror: (err) => reject(err)
    56.                     });
    57.                 });

    58.                 const firstPageData = extractDataFromDoc(firstPageDoc);
    59.                 let totalSum = firstPageData.sum;
    60.                 let totalCount = firstPageData.count;

    61.                 const pgContainer = firstPageDoc.querySelector('.pg');
    62.                 let maxPage = 1, urlTemplate = "";

    63.                 if (pgContainer) {
    64.                     const labelSpan = pgContainer.querySelector('label span');
    65.                     maxPage = labelSpan ? parseInt(labelSpan.title.match(/(\d+)/)[1]) : 1;
    66.                     const link = pgContainer.querySelector('a[href*="page="]');
    67.                     if (link) urlTemplate = (link.href.indexOf('http') === -1 ? window.location.protocol + '//' + window.location.host + '/' + link.getAttribute('href') : link.href).replace(/&amp;/g, '&');
    68.                 }

    69.                 // --- 并发控制核心逻辑 ---
    70.                 if (maxPage > 1 && urlTemplate) {
    71.                     const BATCH_SIZE = 5; // 每组发 5 个请求
    72.                     const DELAY = 500;    // 每组之间休息 0.5 秒

    73.                     for (let i = 2; i <= maxPage; i += BATCH_SIZE) {
    74.                         const currentBatchEnd = Math.min(i + BATCH_SIZE - 1, maxPage);
    75.                         resultSpan.innerHTML = `<span style="color:#007bff;">正在抓取第 ${i}~${currentBatchEnd} 页 (总 ${maxPage} 页)...</span>`;

    76.                         const batchPromises = [];
    77.                         for (let j = i; j <= currentBatchEnd; j++) {
    78.                             const pageUrl = urlTemplate.replace(/page=\d+/, `page=${j}`);
    79.                             batchPromises.push(new Promise(res => {
    80.                                 GM_xmlhttpRequest({
    81.                                     method: "GET",
    82.                                     url: pageUrl,
    83.                                     onload: (r) => res(extractDataFromDoc(parseHTML(r.responseText))),
    84.                                     onerror: () => res({ count: 0, sum: 0 })
    85.                                 });
    86.                             }));
    87.                         }

    88.                         const batchResults = await Promise.all(batchPromises);
    89.                         batchResults.forEach(d => { totalSum += d.sum; totalCount += d.count; });

    90.                         if (currentBatchEnd < maxPage) await sleep(DELAY); // 还没抓完就休息一下
    91.                     }
    92.                 }

    93.                 const sumColor = totalSum >= 0 ? '#1a9c1a' : '#ff0000';
    94.                 resultSpan.innerHTML = `共 <strong>${totalCount}</strong> 条,总变更:<span style="color:${sumColor}; font-weight:bold;">${totalSum > 0 ? '+' : ''}${totalSum}</span>`;

    95.             } catch (err) {
    96.                 resultSpan.innerText = "统计异常";
    97.                 console.error(err);
    98.             } finally {
    99.                 calcBtn.disabled = false;
    100.             }
    101.         };
    102.     }
    103.     setTimeout(init, 500);
    104. })();
    复制代码



    来自群组: 星象占卜

    本帖子中包含更多资源

    您需要 登录 才可以下载或查看,没有账号?立即注册

    x

    评分

    参与人数 4血液 +11 追随 +4 堕落 +4 收起 理由
    leochan + 3 + 1 + 1
    reober3 + 2 + 1 + 1
    PURO_ + 1 + 1 + 1 nice
    娱乐法师火布偶 + 5 + 1 + 1

    查看全部评分

    回复

    使用道具 举报

    炼金之心神秘商店贵宾卡诺克提斯·路西斯·伽拉姆亚当‧简森詹米·多南双贤辉石头罩艾尔登法环

      Se7en 发表于 4 天前 | 显示全部楼层 <
      回复

      使用道具 举报

      光明奇幻木偶『天圆地方』Amicus鎏彩万幢女巫之路虚空之海的鲸永远的克叔業火死鬥实现梦想官复原职

        娱乐法师火布偶 发表于 4 天前 | 显示全部楼层 <
        本帖最后由 娱乐法师火布偶 于 2026-1-31 19:27 编辑

        同理应该也可以统计通过举报获得了多少金币呢
        今年一月的举报收获如下:


        去年2月到12月的举报收获如下:(不能从1月开始统计,超过100页了)

        本帖子中包含更多资源

        您需要 登录 才可以下载或查看,没有账号?立即注册

        x
        回复

        使用道具 举报

        肉乖乖旧日支配者—克苏鲁業火死鬥魔法不朽·传奇不熄十年一梦帅气的本・比格炙热的格拉迪欧拉斯炽焰咆哮虎永浴爱河男巫之歌

          Burry 发表于 4 天前 | 显示全部楼层 <
          回复

          使用道具 举报

          業火死鬥传奇竹取物语Amicus虚空之海的鲸『厢庭望远』『搓粉团珠』『天圆地方』缘起星空鎏彩万幢

            柏芸 发表于 4 天前 | 显示全部楼层 <
            个人觉得看着自己的附件卖了多少似乎还是挺有成就感的,虽然说看下载次数也是一个道理
            回复

            使用道具 举报

            检定场内在命运的轮廓英普瑞斯炽焰咆哮虎亚瑟‧摩根業火死鬥人间之神

              momohang 发表于 4 天前 | 显示全部楼层 <
              谢谢这个! 虽然帖子没有很多但拿来统计一下数据还是很不错的,加上有用上批量兑换,很容易就把之前的数据洗走了

              回复

              使用道具 举报

              近地夜航雷文克劳捡到了肥皂『天圆地方』Amicus光明奇幻木偶遭遇死神诺克提斯·路西斯·伽拉姆

                Rolf_0 发表于 4 天前 | 显示全部楼层 <
                回复

                使用道具 举报

                【夏日限定】夏日的泰凯斯裸体克里斯男用贞操带不曾寄出的信件破损的旧书雪王的心脏幽灵竹筒冒险用指南针GM論壇榮譽勛章龙腾世纪:审判

                  crino66666 发表于 4 天前 | 显示全部楼层 <
                  回复

                  使用道具 举报

                  我的天使GM吸血伯爵吃饱金币的Doge苏格兰圆脸胖鸡小小舞台守卫: 坚守眼位永浴爱河肉垫手套御医神兔『搓粉团珠』

                    毛茸茸兽兽 发表于 4 天前 | 显示全部楼层 <
                    回复

                    使用道具 举报

                    Amicus『天圆地方』光明奇幻木偶You Can Pet Blaidd業火死鬥炽焰咆哮虎暮狼归来使命终成SCP-s-1889-第五页丹雀衔五穗,人间始丰登

                      狂野哈士奇 发表于 4 天前 | 显示全部楼层 <
                      回复

                      使用道具 举报

                      自定义男从Homunculus【夏日限定】夏日的泰凯斯永远的克叔虚空之海的鲸果体76『天圆地方』猫咪点唱机Amicus光明奇幻木偶

                        PURO_ 发表于 4 天前 | 显示全部楼层 <
                        马上要补货了,是不是也可以看自己在补货期间花了多少金币呢,那还蛮有趣的
                          收起(2)
                        回复

                        使用道具 举报

                        萨赫的蛋糕堕落之舞收到情书模擬人生4SCP-s-1889-第七页捡到了肥皂炼金之心

                          lqiang1990 发表于 4 天前 | 显示全部楼层 <
                          回复

                          使用道具 举报

                          捡到了肥皂猫咪点唱机史莱哲林敖蜃星千杯不醉收到情书茉香啤酒雷霆晶球变骚喷雾黑暗交易

                            x14443 发表于 4 天前 | 显示全部楼层 <
                            回复

                            使用道具 举报

                            召唤古代战士克里斯‧雷德菲尔德勋章空位插槽诺克提斯·路西斯·伽拉姆普隆普特·阿金塔姆王者之盾实现梦想传奇GM吸血伯爵

                              lyrt1996 发表于 4 天前 | 显示全部楼层 <
                              看起来是一个很不错的工具诶,不过我个人可能暂时用不上吧(指不关心金币支出
                              回复

                              使用道具 举报

                              泰比里厄斯时间变异管理局双重身份邦尼尼不灭狂雷人鱼之泪帅气的本・比格弗雷迪玩偶妙手空空

                                盘上雷 发表于 4 天前 | 显示全部楼层 <
                                回复

                                使用道具 举报

                                GM論壇初心者畢業證書

                                  喵喵镜你好弱啊 发表于 4 天前 | 显示全部楼层 <
                                  回复

                                  使用道具 举报

                                  帅气的本・比格光明奇幻木偶AmicusBeauty and the Beast肉乖乖遗留之人的城堡吃饱金币的Doge夏日柯基永远的克叔

                                    zibatco2 发表于 4 天前 | 显示全部楼层 <
                                    回复

                                    使用道具 举报

                                    咆哮诅咒史莱哲林神秘商店贵宾卡变骚喷雾收到情书千杯不醉永远的克叔极·龙の意新神的赐福官复原职

                                      2297988 发表于 4 天前 | 显示全部楼层 <
                                      回复

                                      使用道具 举报

                                      性感男神GM传奇幽浮起司煲车厢特供 · 热巧 450ml图腾饼干『酒馆蛋煲』桂花米糕『南瓜拿铁』男巫之歌缘起星空

                                        一只随行 发表于 4 天前 | 显示全部楼层 <
                                        回复

                                        使用道具 举报

                                        【新手友好】昆進萨赫的蛋糕最终幻想XIV山猫图腾猎鹰图腾眼镜蛇图腾寻觅驯化黑龙幼崽

                                          1458209048 发表于 4 天前 | 显示全部楼层 <
                                          回复

                                          使用道具 举报

                                          您需要登录后才可以回帖 登录 | 立即注册

                                          本版积分规则

                                          关闭

                                          站长公告上一条 /1 下一条

                                          文字版|手机版|小黑屋|GameMale

                                          GMT+8, 2026-2-4 08:05 , Processed in 0.220751 second(s), 145 queries , Redis On.

                                          Copyright © 2013-2026 GameMale

                                          All Rights Reserved.

                                          快速回复 返回列表