【油猴脚本】积分记录一键统计
动机像试着统计一下自己究竟通过售卖附件获得了多少金币,就调教Gemini写了这个脚本。虽然最终效果不尽如人意,但由于是对“积分记录”这个页面的大部分选项都有效,或许还有一些我没想到过的用途。
功能
这个脚本在积分记录页面添加了一个“一键统计”按钮,选择好几个限制条件后点击一下,就可以统计出相关的条目数和总的积分变化。
美中不足的是由于论坛限制,超过100页的部分获取不到,会显示“分页数不在允许的范围内”,按照每页20条计算,只能获取到前2000条。如果发帖很多、售卖附件获得金币的条目数也很多的话,就得自己控制时间范围,保证不超过2000条,否则脚本获取不全。
关于对服务器可能造成的压力:脚本以每5页为一组进行抓取,每组之间休息500毫秒;且通过脚本获取的内容全部为文本格式。可以认为对服务器的压力不大。
代码
@Name@Match@Icon
// ==UserScript==
// @name 功能:GameMale积分记录一键统计
// @namespace http://tampermonkey.net/
// @version 1.0
// @description引入并发控制与频率限制,保护服务器,防止触发封禁
// @author Gemini
// @match *://www.gamemale.com/home.php?mod=spacecp&ac=credit&op=log*
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
function parseHTML(html) { return new DOMParser().parseFromString(html, 'text/html'); }
function extractDataFromDoc(doc) {
let count = 0, sum = 0;
const rows = doc.querySelectorAll('table.dt tbody tr');
rows.forEach(row => {
const amountCell = row.querySelector('td:nth-child(2)');
if (amountCell) {
const match = (amountCell.innerText || amountCell.textContent).match(/([-+]?\d+)/);
if (match) {
const value = parseInt(match, 10);
if (!isNaN(value)) { sum += value; count++; }
}
}
});
return { count, sum };
}
// 关键辅助函数:延时
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
function init() {
const form = document.querySelector('form');
const searchBtn = form ? form.querySelector('button') : null;
if (!form || !searchBtn) return;
const calcBtn = document.createElement('button');
calcBtn.type = 'button';
calcBtn.className = 'pn';
calcBtn.style.marginLeft = '10px';
calcBtn.innerHTML = '<strong>一键统计</strong>';
const resultSpan = document.createElement('span');
resultSpan.style.marginLeft = '10px';
resultSpan.style.fontSize = '14px';
searchBtn.parentNode.insertBefore(calcBtn, searchBtn.nextSibling);
searchBtn.parentNode.insertBefore(resultSpan, calcBtn.nextSibling);
calcBtn.onclick = async function() {
resultSpan.innerHTML = '<span style="color:#999;">正在初始化...</span>';
calcBtn.disabled = true;
try {
const formData = new FormData(form);
const firstPageDoc = await new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: "POST",
url: form.action,
data: formData,
onload: (res) => resolve(parseHTML(res.responseText)),
onerror: (err) => reject(err)
});
});
const firstPageData = extractDataFromDoc(firstPageDoc);
let totalSum = firstPageData.sum;
let totalCount = firstPageData.count;
const pgContainer = firstPageDoc.querySelector('.pg');
let maxPage = 1, urlTemplate = "";
if (pgContainer) {
const labelSpan = pgContainer.querySelector('label span');
maxPage = labelSpan ? parseInt(labelSpan.title.match(/(\d+)/)) : 1;
const link = pgContainer.querySelector('a');
if (link) urlTemplate = (link.href.indexOf('http') === -1 ? window.location.protocol + '//' + window.location.host + '/' + link.getAttribute('href') : link.href).replace(/&/g, '&');
}
// --- 并发控制核心逻辑 ---
if (maxPage > 1 && urlTemplate) {
const BATCH_SIZE = 5; // 每组发 5 个请求
const DELAY = 500; // 每组之间休息 0.5 秒
for (let i = 2; i <= maxPage; i += BATCH_SIZE) {
const currentBatchEnd = Math.min(i + BATCH_SIZE - 1, maxPage);
resultSpan.innerHTML = `<span style="color:#007bff;">正在抓取第 ${i}~${currentBatchEnd} 页 (总 ${maxPage} 页)...</span>`;
const batchPromises = [];
for (let j = i; j <= currentBatchEnd; j++) {
const pageUrl = urlTemplate.replace(/page=\d+/, `page=${j}`);
batchPromises.push(new Promise(res => {
GM_xmlhttpRequest({
method: "GET",
url: pageUrl,
onload: (r) => res(extractDataFromDoc(parseHTML(r.responseText))),
onerror: () => res({ count: 0, sum: 0 })
});
}));
}
const batchResults = await Promise.all(batchPromises);
batchResults.forEach(d => { totalSum += d.sum; totalCount += d.count; });
if (currentBatchEnd < maxPage) await sleep(DELAY); // 还没抓完就休息一下
}
}
const sumColor = totalSum >= 0 ? '#1a9c1a' : '#ff0000';
resultSpan.innerHTML = `共 <strong>${totalCount}</strong> 条,总变更:<span style="color:${sumColor}; font-weight:bold;">${totalSum > 0 ? '+' : ''}${totalSum}</span>`;
} catch (err) {
resultSpan.innerText = "统计异常";
console.error(err);
} finally {
calcBtn.disabled = false;
}
};
}
setTimeout(init, 500);
})();
星象占卜 挺方便的這樣就能更直觀的知道畫了多少金幣買附件。 本帖最后由 娱乐法师火布偶 于 2026-1-31 19:27 编辑
同理应该也可以统计通过举报获得了多少金币呢
今年一月的举报收获如下:
去年2月到12月的举报收获如下:(不能从1月开始统计,超过100页了)
数据统计的脚本,特别的方便记录自己金币变化。 个人觉得看着自己的附件卖了多少似乎还是挺有成就感的,虽然说看下载次数也是一个道理:P 谢谢这个! 虽然帖子没有很多但拿来统计一下数据还是很不错的,加上有用上批量兑换,很容易就把之前的数据洗走了
经常发资源的大佬能用得上,看到自己收集的金币一定很满足 倒也是方便不少,感觉这样更清晰了 吼~看3楼还可以知道举报获得多少金币欸,还挺有成就感的 对于常发帖的用户来说是蛮不错的一个统计查看工具呢 马上要补货了,是不是也可以看自己在补货期间花了多少金币呢,那还蛮有趣的{:6_188:}https://img.gamemale.com/album/202508/31/092111u1rzt6h6tzeezd11.jpg 好棒的脚本,确实很想知道,自己的积分详情, 感觉这对于发帖多的大佬才有用呢 ;P像2我这种小卡拉米都是一个个看的;P 看起来是一个很不错的工具诶,不过我个人可能暂时用不上吧(指不关心金币支出 看到统计出来的大数字心里还是满满的成就感 啊,这么好的功能可惜手机不能用 对于发帖大户感觉挺实用的~挺实用的小插件呢~感谢星大佬分享啦;P 不咋举报也不卖附件的俺就只好默默仰望楼上的大佬们了=3= 感觉偶尔统计一下看看大数字也会心情很好哇{:6_184:} 明显就感觉方便许多了,感谢大佬的制作和分享