您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
平均スコアの数値のみ色分け(2.80・2.90含め正確に対応)
// ==UserScript== // @name カクヨム平均スコア表示(数値だけ色と太字・精密比較) // @namespace http://tampermonkey.net/ // @version 1.3 // @description 平均スコアの数値のみ色分け(2.80・2.90含め正確に対応) // @match https://kakuyomu.jp/search* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const handledWorks = new Set(); window.addEventListener('load', () => { setTimeout(() => { const links = Array.from(document.querySelectorAll('a[href^="/works/"]')); const uniqueLinks = [...new Set(links.map(a => a.href))]; for (const url of uniqueLinks) { const workId = url.split('/works/')[1]; if (!workId || handledWorks.has(workId)) continue; handledWorks.add(workId); fetchWorkAverage(url, workId); } }, 2000); }); async function fetchWorkAverage(url, workId) { try { const res = await fetch(url); const html = await res.text(); const jsonText = html.match(/<script id="__NEXT_DATA__" type="application\/json">([\s\S]*?)<\/script>/)?.[1]; if (!jsonText) throw new Error('JSONデータが見つかりません'); const json = JSON.parse(jsonText); const state = json.props?.pageProps?.__APOLLO_STATE__; const workKey = Object.keys(state).find(k => k.startsWith('Work:') && k.includes(workId)); if (!workKey || !state[workKey]) throw new Error('Workデータが見つかりません'); const reviewCount = Number(state[workKey].reviewCount); const totalReviewPoint = Number(state[workKey].totalReviewPoint); if (reviewCount === 0) return; const avgRaw = totalReviewPoint / reviewCount; const avgRounded = Math.round(avgRaw * 100) / 100; // 数値として丸める const avgDisplay = avgRounded.toFixed(2); // 表示用文字列 const anchor = document.querySelector(`a[href="/works/${workId}"]`); if (!anchor) return; const info = document.createElement('div'); info.style.fontSize = '13px'; info.style.marginTop = '4px'; info.style.color = '#444'; const spanScore = document.createElement('span'); spanScore.textContent = avgDisplay; // 数値条件を精密に評価 if (avgRounded >= 2.90) { spanScore.style.color = 'red'; spanScore.style.fontWeight = 'bold'; } else if (avgRounded >= 2.80) { spanScore.style.color = 'green'; spanScore.style.fontWeight = 'bold'; } info.appendChild(document.createTextNode('📊 平均スコア: ')); info.appendChild(spanScore); info.appendChild(document.createTextNode(`(${reviewCount}件)`)); const parent = anchor.closest('div[class^="WorkSummaryItem_root"]') || anchor.parentElement; if (parent) parent.appendChild(info); } catch (e) { console.warn(`❌ ${workId} の取得に失敗しました:`, e); } } })();