// ==UserScript== // @name 原神玩家指示器升级版 // @namespace www.cber.ltd // @version 0.7.1 // @description B站评论区自动标注米哈游玩家,依据动态给B站用户打分,基于laupuz-xu的代码 // @author urlz7 // @match https://www.bilibili.com/video/* // @match https://space.bilibili.com/*/dynamic* // @match https://t.bilibili.com/* // @match https://www.bilibili.com/read/* // @icon https://static.hdslb.com/images/favicon.ico // @connect bilibili.com // @grant GM_xmlhttpRequest // @license MIT // @run-at document-end // @downloadURL none // ==/UserScript== (function() { 'use strict'; const cache = {} const keywords = { "贱长": -8, // 米黑 "原批": -6, "原p": -6, "叩": -6, "欧泡": -6, "哦泡": -6, "糇": -6, "米学长": -6, "米孝子": -6, "mxz": -6, "数一数二": -4, "烧鸡": -3, "米卫兵": -3, "mvb": -3, "op": -2, "米哈游": 3, // 路人 "#miHoYo": 3, "绝区零": 3, "稻妻": 5, "雷电将军": 5, "钟离": 5, "神子": 5, "刻晴": 5, "万叶": 5, "可莉": 5, "提瓦特": 5, "舰长": 5, "须弥": 5, "律者": 5, "原神": 5, "崩坏3": 5, "米黑": 5, // 米卫兵 "魔怔人": 5, "🐒": 5, "🐒吧": 10, "mzr": 20, "赛批": 20, "赛p": 20, "单机批": 20, "单机p": 20, "百万塞尔达": 20, } // 关键词与权重,乱填的,我又不能手工机器学习 const blog = 'https://api.bilibili.com/x/polymer/web-dynamic/v1/feed/space?&host_mid=' const is_new = document.getElementsByClassName('item goback').length != 0 // 检测是不是新版 const get_pid = (c) => { if (is_new) return c.dataset.userId return c.children[0].href.replace(/[^\d]/g, "") } const get_comment_list = () => { if (is_new) { let lst = new Set() for (let c of document.getElementsByClassName('user-name')) { lst.add(c) } for (let c of document.getElementsByClassName('sub-user-name')) { lst.add(c) } return lst } else { return document.getElementsByClassName('user') } } console.log(is_new) console.log("正常加载") let jiance = setInterval(()=>{ let commentlist = get_comment_list() if (commentlist.length != 0){ // clearInterval(jiance) commentlist.forEach(c => { let pid = get_pid(c) if (pid in cache) { if (c.className == "user") { c = c.firstChild; } if (c.textContent.endsWith("】") === false) { console.log(c) c.append(cache[pid]) } return } //console.log(pid) let blogurl = blog + pid let request = (calc, num_iter, more, off) => { if (!more || num_iter == 0) { if (!(pid in cache)) { let normalize = x => 2*(1/(1+Math.exp(-x)) - 0.5) // 归一化 let normalize2 = x => 1/(1+Math.exp(-x)) // 归一化 let stars = (x, n) => "★".repeat(Math.ceil(x*n))+"☆".repeat(n-Math.ceil(x*n)) let yuan = normalize(5*calc.count1/calc.num_posts) || 0 let beng = normalize(5*calc.count2/calc.num_posts) || 0 let zonghepingfen = normalize2(calc.score/calc.num_posts || 0) let elem = `【原:${stars(yuan, 5)} 崩:${stars(beng, 5)} 综合评分:${Math.ceil(zonghepingfen*100)}】` cache[pid] = elem } return } GM_xmlhttpRequest({ method: "get", url: off ? blogurl + "&offset=" + off : blogurl, data: '', headers: { 'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36' }, onload: function(res){ if (res.status === 200){ //console.log('成功') let {data: {has_more, items, offset}} = JSON.parse(res.response) let genshin_count = 0 let honkai3_count = 0 let post_score = 0 items.forEach(item => { let score = 0 let st = JSON.stringify(item) if (st.includes("原神")) genshin_count++ if (st.includes("崩坏3")) honkai3_count++ Object.keys(keywords).forEach(k => { if (st.includes(k)) score += keywords[k] // 乘以权重 }) post_score += score // 单条动态评分 }) request( { count1: calc.count1 + genshin_count, count2: calc.count2 + honkai3_count, score: calc.score + post_score, num_posts: calc.num_posts + items.length, }, num_iter - 1, has_more, offset ) } else{ console.log('失败') console.log(res) } }, }); } request({count1: 0, count2: 0, score: 0, num_posts: 0}, 5, true); // 翻5页动态,最多60条动态,不推荐设太高因为太慢 }); } }, 4000) })();