在雷速移动端网页加入多场比赛亚盘统计功能,点击“统计”后,在每个比分下可以选择特定比赛进行让球亚盘统计,点击“显示”将加载数据并显示统计结果表格。
当前为
// ==UserScript==
// @name 雷速体育亚盘统计
// @namespace http://dol.freevar.com/
// @version 0.81
// @description 在雷速移动端网页加入多场比赛亚盘统计功能,点击“统计”后,在每个比分下可以选择特定比赛进行让球亚盘统计,点击“显示”将加载数据并显示统计结果表格。
// @author Dolphin
// @match https://m.leisu.com/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// @connect pay.jcyqr.com
// @run-at document-idle
// @license MIT
// ==/UserScript==
(function () {
'use strict';
// 样式定义
GM_addStyle(`
input[type="checkbox"] {
-webkit-appearance: auto;
-moz-appearance: auto;
appearance: auto;
width: 4vw;
height: 4vw;
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 { border:1px solid #ccf; text-align:center; padding:0 1vw; }
.highlight-green { background:#cfc }
.highlight-red { background:#fcc }
#analysisButtons button {background:#ccf; padding:1vw 2vw; border-radius:1vw;}
`);
// 全局变量
let selectedMatches = new Map();
let resultContainer = null;
let isShowing = false;
// 添加控制按钮
function addControlButtons() {
const container = document.createElement('div');
container.id = 'analysisButtons';
container.innerHTML = `
<button id="btnStats">统计</button>
<button id="btnToggle">显示</button>
`;
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 = '显示';
isShowing = false;
} else {
// 显示状态
btn.textContent = '加载中';
try {
await fetchAndRenderData();
btn.textContent = '隐藏';
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);
});
}
// 获取并渲染数据
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);
if (initial) {
initialOdds.set(initial.company_name, {
home: initial.home_winner,
draw: initial.draw,
away: initial.away_winner
});
}
if (live) {
liveOdds.set(live.company_name, {
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 = 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 = `
<thead>
<tr>
<th>公司</th>
<th>开盘</th>
<th>命中</th>
<th>命中率</th>
<th>主队</th>
<th>让球</th>
<th>客队</th>
</tr>
</thead>
<tbody></tbody>
`;
// 即时数据表格
const liveTable = document.createElement('table');
liveTable.className = 'stats-table';
liveTable.innerHTML = `
<thead>
<tr>
<th>公司</th>
<th>即时主队</th>
<th>即时让球</th>
<th>即时客队</th>
</tr>
</thead>
<tbody></tbody>
`;
// 填充统计表格
stats.forEach((data, company) => {
const row = statsTable.insertRow();
const initial = initialOdds.get(company) || {};
row.innerHTML = `
<td>${company}</td>
<td>${data.count}</td>
<td>${data.hit}</td>
<td>${data.count ? (data.hit / data.count * 100).toFixed(1) + '%' : ''}</td>
<td>${initial.home || ''}</td>
<td>${initial.draw || ''}</td>
<td>${initial.away || ''}</td>
`;
highlightCells(row.querySelectorAll('td:nth-child(5), td:nth-child(7)'));
});
// 填充即时数据
liveOdds.forEach((data, company) => {
const row = liveTable.insertRow();
row.innerHTML = `
<td>${company}</td>
<td>${data.home}</td>
<td>${data.draw}</td>
<td>${data.away}</td>
`;
highlightCells(row.querySelectorAll('td:nth-child(2), td:nth-child(4)'));
});
// 组装容器
resultContainer.append(statsTable, liveTable);
document.querySelector('div.classTab').after(resultContainer);
}
// 辅助函数
function highlightCells(cells) {
if (cells.length !== 2) return;
const [cellA, cellB] = cells;
const valueA = parseFloat(cellA.textContent);
const valueB = parseFloat(cellB.textContent);
cellA.classList.remove('highlight-green', 'highlight-red');
cellB.classList.remove('highlight-green', 'highlight-red');
if (isNaN(valueA) || isNaN(valueB)) return;
if (valueA < valueB) {
cellA.classList.add('highlight-green');
cellB.classList.add('highlight-red');
} else if (valueA > valueB) {
cellA.classList.add('highlight-red');
cellB.classList.add('highlight-green');
}
}
function generateRandomString(length) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
return Array.from({ length }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
}
function requestOdds(matchId, sign, timestamp) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'GET',
url: `https://pay.jcyqr.com/odds?sign=${sign}×tamp=${timestamp}&match_id=${matchId}&type=4`,
onload: (res) => {
if (res.status === 200) {
try {
resolve(JSON.parse(res.responseText));
} catch (e) {
reject(new Error('数据解析失败'));
}
} else {
reject(new Error(`HTTP ${res.status}`));
}
},
onerror: (err) => reject(err)
});
});
}
//链接替换成数据页面并在新窗口打开
function modifyLink(a) {
const originalHref = a.getAttribute('href');
if (originalHref && originalHref.includes('/live/detail-')) {
const newHref = originalHref.replace('/live/detail-', '/live/data-');
a.setAttribute('href', newHref);
}
a.setAttribute('target', '_blank');
}
function livePageMod() {
document.getElementById('MatchTopBanner').style.display = "none";
// 初始处理已有链接
document.querySelectorAll('#ftb_live li a.linkk').forEach(a => {
modifyLink(a);
});
// 使用MutationObserver监控动态加载的内容
const observer = new MutationObserver(mutations => {
for (const mutation of mutations) {
for (const node of mutation.addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE && node.matches('li.ftb-lier-base')) {
const link = node.querySelector('a.linkk');
if (link) modifyLink(link);
}
}
}
});
// 开始观察列表容器
const listContainer = document.getElementById('ftb_live');
if (listContainer) {
observer.observe(listContainer, {
childList: true,
subtree: false
});
}
}
//根据网址初始化
if (/^https:\/\/m\.leisu\.com\/live\/?$/.test(window.location.href)) {
setTimeout(livePageMod, 4000);
} else if (window.location.pathname.startsWith('/live/data-')) {
setTimeout(addControlButtons, 4000);
}
})();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址