您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
获取话题参与者用户及角色
// ==UserScript== // @name WoD 获取话题参与者用户及角色 // @icon http://info.world-of-dungeons.org/wod/css/WOD.gif // @namespace http://tampermonkey.net/ // @description 获取话题参与者用户及角色 // @author Christophero // @version 2023.03.24.1 // @match http*://*.world-of-dungeons.org/* // @require https://code.jquery.com/jquery-3.3.1.min.js // @require https://code.jquery.com/ui/1.13.2/jquery-ui.min.js // @grant none // ==/UserScript== (function () { ("use strict"); main(); /** * 插件主入口 */ function main() { initBtn(); } function initBtn() { const $btn = $('<button type="button" class="button">参与者统计</button>'); const $per = $('<span id="calcPer"></span>'); $(".boardspacer:first tr:first td:eq(2)").prepend($btn).prepend($per); $btn.click(fetchTopicParticipant); } async function fetchTopicParticipant() { // 查看有多少页 const $lastPageAnchor = $( 'tr.boardhead a[href^="/wod/spiel/forum/viewtopic.php?"]:last' ); const total = parseInt($lastPageAnchor.text()) || 1; // 获得话题ID const searchParams = new URLSearchParams( (total == 1 ? location.search : $lastPageAnchor.attr("href")).split( "?" )[1] ); const topicId = searchParams.get("id"); const board = searchParams.get("board"); // 遍历页面获得用户及英雄 let finishCnt = 0; const partMap = new Map(); const $per = $("#calcPer"); $per.text(`0/${total}`); for (let i = 0; i < total; i++) { await fetch( `${location.protocol}//delta.world-of-dungeons.org/wod/spiel/forum/viewtopic.php?id=${topicId}&board=${board}&p=${i}&IS_POPUP=1` ) .then((response) => { return response.text(); }) .then((html) => { finishCnt += 1; $per.text(`${finishCnt}/${total}`); const $doc = $(html); const $heros = $doc.find(".boardheadline"); $heros.each(async (i, e) => { let heroName = $(e).text().trim(); let player = $(e) .parents("td:first") .find('a[href^="/wod/spiel/profiles/player.php?"]') .text() .trim(); if (player == "") { player = await fetchPlayerByHero(heroName); heroName = heroName + "【可能转职】"; } if (player == "") { player = heroName + "【异常】"; } if (!partMap.has(player)) { partMap.set(player, new Set()); } partMap.get(player).add(heroName); }); return new Promise((resolve, reject) => { resolve(true); }); }); } $per.text("统计完成"); outputResult(partMap); } /** * 根据英雄名称获得用户名 * @param {*} heroName * @returns */ async function fetchPlayerByHero(heroName) { const response = await fetch( `${ location.protocol }//delta.world-of-dungeons.org/wod/spiel/hero/profile.php?name=${encodeURIComponent( heroName )}&IS_POPUP=1&is_popup=1` ); const text = await response.text(); const jq = $(text); $("#heroCurrent").text(parseInt($("#heroCurrent").text()) + 1); if (jq.find('h1:contains("没有找到")').length) { // 没有找到英雄 return ""; } const player = jq .find('a[href^="/wod/spiel/profiles/player.php?"]') .text() .trim(); return player; } function outputResult(partMap) { let result = "用户,英雄\n"; partMap.forEach((heroes, player) => { result += `${player},${[...heroes].join("|")}\n`; }); console.log(result); exportFile(result, "分析内容.csv"); } /** * 导出文件的方法,导出并直接进行下载 * * @param {String} 传入导出文件的数据, 格式为字符串 * @param {String} 导出文件的文件名称 */ const exportFile = (text = "", filename = "分析内容.txt") => { // 导出数据 const blob = new Blob([text]); const e = new MouseEvent("click"); const a = document.createElement("a"); a.download = filename; a.href = window.URL.createObjectURL(blob); a.dispatchEvent(e); }; })();