// ==UserScript==
// @name 雷速体育亚盘统计
// @namespace http://dol.freevar.com/
// @version 0.85
// @description 在雷速移动端网页加入多场比赛亚盘统计功能,点击“选赛”后,在每个比分下可以选择特定比赛进行让球亚盘统计,点击“统计”将加载数据并显示统计结果表格。
// @author Dolphin
// @match https://m.leisu.com/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @connect pay.jcyqr.com
// @run-at document-idle
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/529697/%E9%9B%B7%E9%80%9F%E4%BD%93%E8%82%B2%E4%BA%9A%E7%9B%98%E7%BB%9F%E8%AE%A1.user.js
// @updateURL https://update.greasyfork.icu/scripts/529697/%E9%9B%B7%E9%80%9F%E4%BD%93%E8%82%B2%E4%BA%9A%E7%9B%98%E7%BB%9F%E8%AE%A1.meta.js
// ==/UserScript==
(function () {
'use strict';
// 样式定义
GM_addStyle(`
input[type="checkbox"] {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
width: 5vw;
height: 5vw;
border: initial;
background: initial;
}
.stats-table { border-collapse:collapse; margin:auto;}
.stats-table tr:nth-child(odd) {background:#fff;}
.stats-table td, .stats-table th { font-size:4vw; border:1px solid #ccc; text-align:center; padding:0 1vw; }
.highlight-green { background:#cfc }
.highlight-red { background:#fcc }
#analysisButtons button {background:#fd4; padding:1vw 3vw; border-radius:1vw;}
`);
// 修改UserAgent
Object.defineProperty(navigator, 'userAgent', {
value: 'Mozilla/5.0 (Linux; Android 14; SM-G975F) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Mobile Safari/537.36 MicroMessenger/6.7.3.1360(0x26070336) NetType/WIFI Language/zh_CN',
configurable: true,
writable: false,
});
// 全局变量
let selectedMatches = new Map();
let resultContainer = null;
let isShowing = false;
const companyNameMap = {
'BE****': 'Bet365',
'澳****': '澳门',
'皇****': '皇冠',
'金****': '金宝博',
'No****': '1xBet',
'香****': '香港',
'易****': '易胜博',
'Red****': '平博',
'18****': '18Bet',
'盈****': '盈禾',
'利****': '利记',
'壹****': '12Bet',
'In****': 'Interw',
'伟****': '伟德',
'威****': '威廉',
'明****': '明陞',
'立****': '立博'
};
// 添加控制按钮
function addControlButtons() {
const adbanner=document.querySelector('div.detail-banner');
if(adbanner) adbanner.style.display='none';
const container = document.createElement('div');
container.id = 'analysisButtons';
container.innerHTML = `
`;
document.querySelector('div.classTab').appendChild(container);
// 绑定事件
document.getElementById('btnStats').addEventListener('click', replaceMintxt);
document.getElementById('btnToggle').addEventListener('click', toggleAnalysis);
}
// 切换显示状态
async function toggleAnalysis() {
const btn = document.getElementById('btnToggle');
if (isShowing) {
// 隐藏状态
if (resultContainer) {
resultContainer.remove();
resultContainer = null;
}
btn.textContent = '统计';
btn.style.background='#fd4';
isShowing = false;
} else {
// 显示状态
btn.style.background='#f66';
btn.textContent = '加载中';
try {
await fetchAndRenderData();
btn.textContent = '删表';
btn.style.background='#6be';
isShowing = true;
} catch (e) {
btn.textContent = '统计';
alert('数据加载失败: ' + e);
}
}
}
// 替换mintxt为复选框
function replaceMintxt() {
document.querySelectorAll('p.mintxt').forEach(p => {
const parent = p.closest('.leisu-tab-td');
const link = parent.querySelector('a[href^="/live/detail-"]');
if (!link) return;
const matchId = link.href.split('-').pop();
link.setAttribute('href', link.href.replace('/detail-', '/data-'));
link.setAttribute('target', '_blank');
// 获取比分差值
const scoreText = p.previousElementSibling.textContent;
const [home, away] = scoreText.split('-').map(Number);
const diff = home - away;
// 创建复选框
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.addEventListener('click', function (e) {
e.stopPropagation();
});
checkbox.addEventListener('change', e => {
if (e.target.checked) {
selectedMatches.set(matchId, diff);
} else {
selectedMatches.delete(matchId);
}
});
p.replaceWith(checkbox);
});
const stbtn=document.getElementById('btnStats');
stbtn.textContent = '✅';
}
// 获取并渲染数据
async function fetchAndRenderData() {
const timestamp = Date.now();
const sign = generateRandomString(32);
const currentMatchId = window.location.pathname.split('-').pop();
// 获取当前比赛数据
const currentData = await requestOdds(currentMatchId, sign, timestamp);
const { initialOdds, liveOdds } = processCurrentData(currentData);
// 获取选中比赛数据
const statsRequests = [];
for (const [matchId, diff] of selectedMatches) {
statsRequests.push(
requestOdds(matchId, sign, timestamp)
.then(data => ({ matchId, data }))
.catch(e => {
alert(`比赛 ${matchId} 获取亚盘数据失败: ${e.message}`);
return null;
})
);
}
const statsResults = await Promise.all(statsRequests);
const companyStats = processStatsData(statsResults);
// 渲染结果
renderAnalysisResult(companyStats, initialOdds, liveOdds);
}
// 处理当前比赛数据
function processCurrentData(data) {
const initialOdds = new Map();
const liveOdds = new Map();
data.data.forEach(companyGroup => {
const initial = companyGroup.find(e => e.is_begin_odds === 1);
const live = companyGroup.find(e => e.is_begin_odds === 0);
const getCompanyName = (entry) => companyNameMap[entry.company_name] || entry.company_name;
if (initial) {
const company = getCompanyName(initial);
initialOdds.set(company, {
home: initial.home_winner,
draw: initial.draw,
away: initial.away_winner
});
}
if (live) {
const company = getCompanyName(live);
liveOdds.set(company, {
home: live.home_winner,
draw: live.draw,
away: live.away_winner
});
}
});
return { initialOdds, liveOdds };
}
// 处理统计数据
function processStatsData(allData) {
const stats = new Map();
allData.forEach(({ matchId, data }) => {
data.data.forEach(companyGroup => {
companyGroup.forEach(entry => {
if (entry.is_begin_odds !== 1) return;
const company = companyNameMap[entry.company_name] || entry.company_name;
if (!stats.has(company)) {
stats.set(company, {
count: 0,
hit: 0,
home: entry.home_winner,
draw: entry.draw,
away: entry.away_winner
});
}
const record = stats.get(company);
record.count++;
// 获取当前比赛的差值
const diff = selectedMatches.get(matchId);
if (typeof diff !== 'number') return;
const draw = parseFloat(entry.draw);
if (diff === draw) {
record.hit++;
} else if (diff > draw && entry.home_winner < entry.away_winner) {
record.hit++;
} else if (diff < draw && entry.away_winner < entry.home_winner) {
record.hit++;
}
});
});
});
return stats;
}
// 渲染分析结果
function renderAnalysisResult(stats, initialOdds, liveOdds) {
// 清理旧容器
if (resultContainer) {
resultContainer.remove();
}
resultContainer = document.createElement('div');
resultContainer.className = 'stats-container';
// 统计表格
const statsTable = document.createElement('table');
statsTable.className = 'stats-table';
statsTable.innerHTML = `
公司
开盘
命中
命中率
主队
让球
客队