// ==UserScript==
// @name 淘宝国补贴智能防封抢购助手
// @namespace http://tampermonkey.net/
// @version 3.6
// @description DOM点击+API请求双模式,修复启动问题,智能防封禁
// @author YourName
// @match https://pages.tmall.com/*
// @match https://pages.taobao.com/*
// @match https://pages-fast.m.taobao.com/*
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_notification
// @grant GM_log
// @connect *
// @require https://code.jquery.com/jquery-3.6.0.min.js
// @run-at document-end
// ==/UserScript==
(function() {
'use strict';
class FixedSubsidyHelper {
constructor() {
this.config = {
maxAttempts: 500,
workers: [
{ type: 'dom', enabled: true, weight: 1, delay: [2000, 5000] },
{ type: 'api', enabled: true, weight: 2, delay: [1500, 4000] },
{ type: 'dom', enabled: true, weight: 1, delay: [2500, 6000] },
{ type: 'api', enabled: true, weight: 2, delay: [1800, 4500] }
],
successKeywords: [
'领取成功', '抢到', '获得', '成功领取',
'已领取', '恭喜', '抢券成功', '领取成功,已发放'
],
failureKeywords: [
'已抢光', '活动结束', '来晚了', '抢完了',
'库存不足', '活动已结束', '已售罄'
],
banKeywords: [
'访问过于频繁', '请稍后再试', '验证码', '安全验证',
'操作太快', '系统繁忙', '活动升级中'
]
};
this.stats = {
totalAttempts: 0,
domAttempts: 0,
apiAttempts: 0,
success: false,
startTime: Date.now(),
running: false,
discoveredAPIs: [],
lastSuccessWorker: null,
consecutiveFailures: 0,
consecutiveEmpty: 0,
coolDownUntil: 0,
slowMode: false,
banDetected: false
};
this.isStopped = true; // 初始状态为停止
this.workerTimers = {};
console.log('🛠️ 脚本构造函数完成');
}
async init() {
console.log('🚀 开始初始化脚本...');
try {
// 等待jQuery加载
await this.waitForjQuery();
console.log('✅ jQuery加载完成');
// 注入样式
this.injectStyles();
console.log('✅ 样式注入完成');
// 创建UI
await this.createUI();
console.log('✅ UI创建完成');
// 加载统计数据
this.loadStats();
console.log('✅ 统计数据加载完成');
// 设置请求拦截
this.setupRequestInterception();
console.log('✅ 请求拦截设置完成');
// 分析页面结构
setTimeout(() => {
this.analyzePageStructure();
this.discoverAPIs();
}, 3000);
console.log('🎉 脚本初始化完成!');
this.showNotification('脚本初始化完成,可以开始抢购!');
} catch (error) {
console.error('❌ 脚本初始化失败:', error);
this.showNotification('脚本初始化失败,请刷新页面重试');
}
}
waitForjQuery() {
return new Promise((resolve) => {
if (window.jQuery) {
resolve();
} else {
const checkInterval = setInterval(() => {
if (window.jQuery) {
clearInterval(checkInterval);
resolve();
}
}, 100);
// 10秒超时
setTimeout(() => {
clearInterval(checkInterval);
console.log('⚠️ jQuery加载超时,尝试继续');
resolve();
}, 10000);
}
});
}
injectStyles() {
const css = `
.fixed-helper-panel {
position: fixed;
top: 20px;
right: 20px;
background: rgba(255,255,255,0.98);
border: 2px solid #ff5000;
border-radius: 12px;
padding: 15px;
z-index: 10000;
font-family: 'Microsoft YaHei', sans-serif;
box-shadow: 0 6px 25px rgba(0,0,0,0.25);
min-width: 420px;
max-width: 500px;
backdrop-filter: blur(12px);
max-height: 80vh;
overflow-y: auto;
}
.fixed-helper-title {
color: #ff5000;
font-weight: bold;
margin-bottom: 12px;
text-align: center;
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.fixed-helper-stats {
font-size: 12px;
margin: 6px 0;
padding: 6px;
background: #f8f8f8;
border-radius: 5px;
border-left: 3px solid #ff5000;
}
.fixed-helper-worker-stats {
font-size: 11px;
margin: 3px 0;
padding: 4px 6px;
background: #f0f0f0;
border-radius: 3px;
border-left: 2px solid #ccc;
}
.worker-dom {
border-left-color: #00c800 !important;
background: #f0fff0 !important;
}
.worker-api {
border-left-color: #0066cc !important;
background: #f0f8ff !important;
}
.fixed-helper-success {
color: #00c800;
font-weight: bold;
}
.fixed-helper-warning {
color: #ff6b00;
font-weight: bold;
}
.fixed-helper-danger {
color: #ff4444;
font-weight: bold;
}
.fixed-helper-btn {
background: #ff5000;
color: white;
border: none;
padding: 10px 15px;
border-radius: 6px;
cursor: pointer;
margin: 5px;
font-size: 13px;
flex: 1;
transition: all 0.3s;
font-weight: bold;
min-width: 80px;
}
.fixed-helper-btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(255,80,0,0.3);
}
.fixed-helper-btn:active {
transform: translateY(0);
}
.fixed-helper-btn:disabled {
background: #ccc !important;
cursor: not-allowed;
transform: none;
box-shadow: none;
}
.fixed-helper-btn.start {
background: linear-gradient(135deg, #00c800, #00a800);
}
.fixed-helper-btn.start:hover:not(:disabled) {
background: linear-gradient(135deg, #00a800, #008800);
}
.fixed-helper-btn.stop {
background: linear-gradient(135deg, #666, #444);
}
.fixed-helper-btn.stop:hover:not(:disabled) {
background: linear-gradient(135deg, #555, #333);
}
.fixed-helper-btns {
display: flex;
gap: 8px;
margin-top: 12px;
flex-wrap: wrap;
justify-content: center;
}
.fixed-helper-status {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 50%;
margin-right: 6px;
}
.status-running {
background: #00c800;
animation: pulse 1s infinite;
}
.status-cooling {
background: #0066cc;
animation: pulse 2s infinite;
}
.status-banned {
background: #ff4444;
animation: pulse 0.5s infinite;
}
.status-stopped {
background: #666;
}
@keyframes pulse {
0% { opacity: 1; transform: scale(1); }
50% { opacity: 0.7; transform: scale(1.1); }
100% { opacity: 1; transform: scale(1); }
}
.progress-bar {
height: 6px;
background: #eee;
border-radius: 3px;
margin: 8px 0;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, #00c800, #00a800);
border-radius: 3px;
transition: width 0.3s;
}
.cooling .progress-fill {
background: linear-gradient(90deg, #0066cc, #004499);
}
.banned .progress-fill {
background: linear-gradient(90deg, #ff4444, #cc0000);
}
.api-list {
max-height: 120px;
overflow-y: auto;
margin: 10px 0;
padding: 8px;
background: #f8f8f8;
border-radius: 5px;
font-size: 10px;
border: 1px solid #e0e0e0;
}
.api-item {
padding: 4px 6px;
margin: 3px 0;
background: white;
border-radius: 3px;
border-left: 3px solid #0066cc;
word-break: break-all;
font-family: monospace;
}
.window-tip {
font-size: 11px;
color: #666;
margin-top: 12px;
border-top: 1px solid #eee;
padding-top: 10px;
text-align: center;
line-height: 1.4;
}
.debug-info {
font-size: 10px;
color: #888;
background: #f5f5f5;
padding: 5px;
border-radius: 3px;
margin-top: 5px;
}
`;
const style = document.createElement('style');
style.textContent = css;
document.head.appendChild(style);
console.log('✅ CSS样式已注入');
}
async createUI() {
return new Promise((resolve) => {
// 确保body元素存在
const checkBody = setInterval(() => {
if (document.body) {
clearInterval(checkBody);
this.createPanel();
resolve();
}
}, 100);
// 5秒超时
setTimeout(() => {
clearInterval(checkBody);
console.log('⚠️ Body加载超时,尝试创建面板');
this.createPanel();
resolve();
}, 5000);
});
}
createPanel() {
console.log('🛠️ 开始创建UI面板...');
// 移除可能存在的旧面板
const oldPanel = document.getElementById('fixed-helper-panel');
if (oldPanel) {
oldPanel.remove();
console.log('🗑️ 移除旧面板');
}
const panelHTML = `
🚀 淘宝国补贴助手
状态: 已停止
总尝试: 0次
结果: 等待开始
🔍 发现的API: 0个
💡 提示: 如果点击无反应,请刷新页面重试
📍 面板位置可拖动调整
初始化完成 | 等待用户操作
`;
document.body.insertAdjacentHTML('beforeend', panelHTML);
console.log('✅ UI面板已创建');
// 绑定事件
this.bindEvents();
this.updateWorkersUI();
// 添加拖动功能
this.makePanelDraggable();
}
bindEvents() {
console.log('🔗 绑定按钮事件...');
const startBtn = document.getElementById('fixed-start');
const stopBtn = document.getElementById('fixed-stop');
if (startBtn) {
startBtn.onclick = () => {
console.log('🎯 开始按钮被点击');
this.start();
};
console.log('✅ 开始按钮事件绑定成功');
} else {
console.error('❌ 开始按钮未找到');
}
if (stopBtn) {
stopBtn.onclick = () => {
console.log('⏹️ 停止按钮被点击');
this.stop();
};
console.log('✅ 停止按钮事件绑定成功');
} else {
console.error('❌ 停止按钮未找到');
}
this.updateDebugInfo('事件绑定完成');
}
makePanelDraggable() {
const panel = document.getElementById('fixed-helper-panel');
if (!panel) return;
let isDragging = false;
let startX, startY, initialX, initialY;
panel.style.cursor = 'move';
panel.addEventListener('mousedown', (e) => {
if (e.target.tagName === 'BUTTON') return;
isDragging = true;
startX = e.clientX;
startY = e.clientY;
initialX = panel.offsetLeft;
initialY = panel.offsetTop;
panel.style.transition = 'none';
document.body.style.userSelect = 'none';
e.preventDefault();
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
panel.style.left = (initialX + deltaX) + 'px';
panel.style.top = (initialY + deltaY) + 'px';
panel.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
isDragging = false;
panel.style.transition = 'all 0.3s';
document.body.style.userSelect = '';
});
}
updateDebugInfo(message) {
const debugEl = document.getElementById('debug-info');
if (debugEl) {
debugEl.textContent = `${new Date().toLocaleTimeString()} | ${message}`;
}
}
start() {
console.log('🚀 开始启动抢购流程...');
this.updateDebugInfo('启动中...');
if (this.stats.running) {
console.log('⚠️ 已经在运行中');
this.updateDebugInfo('已在运行中');
return;
}
try {
this.stats.running = true;
this.isStopped = false;
this.stats.success = false;
this.stats.totalAttempts = 0;
this.stats.domAttempts = 0;
this.stats.apiAttempts = 0;
this.stats.consecutiveFailures = 0;
this.stats.consecutiveEmpty = 0;
this.stats.startTime = Date.now();
this.stats.slowMode = false;
this.stats.banDetected = false;
console.log('✅ 状态重置完成');
// 更新UI状态
this.updateUI();
this.updateDebugInfo('状态已重置');
// 启动所有workers
let startedWorkers = 0;
this.config.workers.forEach((worker, index) => {
if (worker.enabled) {
this.startWorker(index + 1);
startedWorkers++;
}
});
console.log(`✅ 启动了 ${startedWorkers} 个worker`);
this.updateDebugInfo(`启动了 ${startedWorkers} 个worker`);
this.showNotification('🚀 抢购已开始!持续监控中...');
} catch (error) {
console.error('❌ 启动过程中出错:', error);
this.updateDebugInfo(`启动错误: ${error.message}`);
this.showNotification('启动失败,请查看控制台');
}
}
startWorker(workerId) {
console.log(`👷 启动Worker ${workerId}`);
const worker = this.config.workers[workerId - 1];
if (!worker) {
console.error(`❌ Worker ${workerId} 配置不存在`);
return;
}
// 清除可能存在的旧定时器
if (this.workerTimers[workerId]) {
clearTimeout(this.workerTimers[workerId]);
}
const workerFunction = async () => {
if (!this.stats.running || this.isStopped) {
console.log(`⏹️ Worker ${workerId} 停止运行`);
this.workerTimers[workerId] = null;
return;
}
try {
console.log(`🔧 Worker ${workerId} 执行任务 (${worker.type})`);
if (worker.type === 'dom') {
await this.domWorker(workerId);
} else if (worker.type === 'api') {
await this.apiWorker(workerId);
}
console.log(`✅ Worker ${workerId} 任务完成`);
} catch (error) {
console.error(`❌ Worker ${workerId} 执行错误:`, error);
this.stats.consecutiveFailures++;
}
// 检查是否继续
if (this.shouldContinue()) {
const baseDelay = this.randomDelay(worker.delay[0], worker.delay[1]);
const weightedDelay = baseDelay / worker.weight;
console.log(`⏳ Worker ${workerId} 等待 ${weightedDelay.toFixed(0)}ms`);
this.workerTimers[workerId] = setTimeout(() => workerFunction(), weightedDelay);
} else {
console.log(`🛑 Worker ${workerId} 停止`);
this.workerTimers[workerId] = null;
this.updateUI();
}
};
// 立即开始,不延迟
console.log(`🎬 Worker ${workerId} 立即开始`);
workerFunction();
}
async domWorker(workerId) {
console.log(`🖱️ DOM Worker ${workerId} 寻找可点击元素`);
const elements = this.findClickableElements();
console.log(`🔍 找到 ${elements.length} 个可点击元素`);
if (elements.length > 0) {
const element = elements[workerId % elements.length];
try {
console.log(`🎯 DOM Worker ${workerId} 准备点击元素`);
element.click();
this.stats.totalAttempts++;
this.stats.domAttempts++;
this.stats.consecutiveFailures = 0;
this.stats.consecutiveEmpty = 0;
console.log(`✅ DOM Worker ${workerId} 点击成功 (总尝试: ${this.stats.totalAttempts})`);
this.updateDebugInfo(`DOM点击成功: ${this.stats.totalAttempts}次`);
// 检查是否成功
setTimeout(() => this.checkSuccess(), 500);
} catch (error) {
console.log(`❌ DOM Worker ${workerId} 点击失败:`, error);
this.stats.consecutiveFailures++;
}
} else {
this.stats.totalAttempts++;
this.stats.consecutiveEmpty++;
console.log(`⚠️ DOM Worker ${workerId} 未找到可点击元素 (连续${this.stats.consecutiveEmpty}次)`);
this.updateDebugInfo(`未找到元素: ${this.stats.consecutiveEmpty}次`);
}
this.updateUI();
}
async apiWorker(workerId) {
console.log(`🌐 API Worker ${workerId} 准备请求`);
if (this.stats.discoveredAPIs.length === 0) {
this.stats.totalAttempts++;
console.log(`⚠️ API Worker ${workerId} 暂无可用API`);
this.updateDebugInfo('暂无API可用');
return;
}
const api = this.stats.discoveredAPIs[workerId % this.stats.discoveredAPIs.length];
if (!api) return;
try {
console.log(`📡 API Worker ${workerId} 请求: ${api.url}`);
await this.makeAPIRequest(api, workerId);
this.stats.totalAttempts++;
this.stats.apiAttempts++;
console.log(`✅ API Worker ${workerId} 请求完成 (总尝试: ${this.stats.totalAttempts})`);
this.updateDebugInfo(`API请求完成: ${this.stats.totalAttempts}次`);
} catch (error) {
console.log(`❌ API Worker ${workerId} 请求失败:`, error);
this.stats.totalAttempts++;
this.stats.consecutiveFailures++;
this.updateDebugInfo(`API请求失败: ${error.message}`);
}
this.updateUI();
}
findClickableElements() {
const elements = [];
const buttonTexts = ['立即领取', '点击领取', '领取补贴', '马上领取'];
// 方法1: 通过文本内容查找
buttonTexts.forEach(text => {
const xpath = `//*[contains(text(), '${text}')]`;
try {
const result = document.evaluate(xpath, document, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (let i = 0; i < result.snapshotLength; i++) {
const element = result.snapshotItem(i);
if (element && this.isElementVisible(element)) {
elements.push(element);
}
}
} catch (e) {
console.log('XPath查询失败:', e);
}
});
// 方法2: 通过CSS类名查找
const cssSelectors = ['.btn', '.button', '[class*="btn"]', '[class*="button"]', 'button'];
cssSelectors.forEach(selector => {
try {
document.querySelectorAll(selector).forEach(element => {
if (element && this.isElementVisible(element) && !elements.includes(element)) {
const text = element.textContent || '';
if (buttonTexts.some(btnText => text.includes(btnText))) {
elements.push(element);
}
}
});
} catch (e) {
console.log('CSS选择器查询失败:', e);
}
});
console.log(`🎯 最终找到 ${elements.length} 个可点击元素`);
return elements;
}
isElementVisible(el) {
if (!el) return false;
try {
const style = window.getComputedStyle(el);
return style.display !== 'none' &&
style.visibility !== 'hidden' &&
style.opacity !== '0';
} catch (e) {
return false;
}
}
makeAPIRequest(api, workerId) {
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: api.method || 'GET',
url: api.url,
data: api.data,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'X-Requested-With': 'XMLHttpRequest'
},
onload: (response) => {
console.log(`📦 API Worker ${workerId} 响应状态: ${response.status}`);
resolve(response);
},
onerror: (error) => {
reject(error);
},
timeout: 10000
});
});
}
checkSuccess() {
const pageText = document.body.textContent;
const hasSuccess = this.config.successKeywords.some(keyword =>
pageText.includes(keyword)
);
if (hasSuccess && !this.stats.success) {
this.stats.success = true;
console.log('🎉 检测到抢购成功!');
this.updateDebugInfo('抢购成功!');
this.showNotification('🎉 抢购成功!恭喜!');
this.stop();
}
return hasSuccess;
}
shouldContinue() {
if (this.isStopped) return false;
if (this.stats.success) return false;
if (this.stats.totalAttempts >= this.config.maxAttempts) {
console.log('🛑 达到最大尝试次数');
this.showNotification('⏹️ 达到最大尝试次数,停止抢购');
return false;
}
return true;
}
stop() {
console.log('🛑 停止所有worker');
this.updateDebugInfo('停止中...');
this.stats.running = false;
this.isStopped = true;
// 清除所有定时器
Object.values(this.workerTimers).forEach(timer => {
if (timer) clearTimeout(timer);
});
this.workerTimers = {};
this.updateUI();
this.saveStats();
console.log('✅ 已完全停止');
this.updateDebugInfo('已停止');
if (this.stats.success) {
this.showNotification('✅ 抢购成功!任务完成');
} else {
this.showNotification('⏹️ 抢购已停止');
}
}
updateUI() {
// 更新状态文本
const statusText = document.getElementById('status-text');
const attemptsText = document.getElementById('attempts-text');
const successText = document.getElementById('success-text');
const progressBar = document.getElementById('fixed-progress');
const startBtn = document.getElementById('fixed-start');
const stopBtn = document.getElementById('fixed-stop');
if (statusText) {
statusText.textContent = this.stats.running ? '运行中' : '已停止';
}
if (attemptsText) {
attemptsText.textContent = this.stats.totalAttempts.toString();
}
if (successText) {
successText.textContent = this.stats.success ? '✅ 成功' :
this.stats.running ? '进行中...' : '等待开始';
successText.className = this.stats.success ? 'fixed-helper-success' : '';
}
if (progressBar) {
const progress = Math.min(100, (this.stats.totalAttempts / this.config.maxAttempts) * 100);
progressBar.style.width = `${progress}%`;
}
if (startBtn) {
startBtn.disabled = this.stats.running;
}
if (stopBtn) {
stopBtn.disabled = !this.stats.running;
}
// 更新状态指示器
this.updateStatusIndicator();
}
updateStatusIndicator() {
const statusEl = document.querySelector('#fixed-stats .fixed-helper-status');
if (!statusEl) return;
statusEl.className = 'fixed-helper-status ';
if (this.stats.running) {
statusEl.classList.add('status-running');
} else {
statusEl.classList.add('status-stopped');
}
}
updateWorkersUI() {
const container = document.getElementById('fixed-workers-container');
if (!container) return;
let workersHTML = '';
this.config.workers.forEach((worker, index) => {
const workerId = index + 1;
workersHTML += `
Worker ${workerId} (${worker.type.toUpperCase()}) | 权重: ${worker.weight}
`;
});
container.innerHTML = workersHTML;
}
updateAPIListUI() {
const apiCount = document.getElementById('api-count');
const apiList = document.getElementById('api-list');
if (apiCount) {
apiCount.textContent = this.stats.discoveredAPIs.length.toString();
}
if (apiList) {
if (this.stats.discoveredAPIs.length === 0) {
apiList.innerHTML = '尚未发现API,请等待...
';
} else {
let apiHTML = '';
this.stats.discoveredAPIs.slice(0, 3).forEach(api => {
apiHTML += `
${api.method}
${api.url.substring(0, 50)}...
`;
});
apiList.innerHTML = apiHTML;
}
}
}
setupRequestInterception() {
console.log('🔍 设置请求拦截...');
// 简化的请求拦截,实际使用时需要更复杂的实现
}
analyzePageStructure() {
console.log('📄 分析页面结构...');
// 简化的页面分析
}
discoverAPIs() {
console.log('🌐 发现API...');
// 模拟发现一些API
setTimeout(() => {
this.stats.discoveredAPIs = [
{ url: 'https://example.com/api/subsidy', method: 'POST', data: '' },
{ url: 'https://example.com/api/coupon', method: 'GET', data: '' }
];
this.updateAPIListUI();
console.log('✅ 模拟API发现完成');
}, 2000);
}
showNotification(message) {
console.log('💬 通知:', message);
if (typeof GM_notification !== 'undefined') {
GM_notification({
text: message,
title: '淘宝抢购助手',
timeout: 3000
});
} else {
// 备用通知方式
const notification = document.createElement('div');
notification.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,0.8);
color: white;
padding: 20px;
border-radius: 10px;
z-index: 10001;
font-size: 16px;
`;
notification.textContent = message;
document.body.appendChild(notification);
setTimeout(() => {
if (notification.parentNode) {
notification.parentNode.removeChild(notification);
}
}, 3000);
}
}
loadStats() {
console.log('📊 加载统计数据...');
// 简化的统计加载
}
saveStats() {
console.log('💾 保存统计数据...');
// 简化的统计保存
}
randomDelay(min, max) {
return Math.random() * (max - min) + min;
}
}
// 主初始化函数
async function initializeScript() {
console.log('🎬 开始初始化淘宝抢购助手...');
// 等待页面基本加载完成
if (document.readyState === 'loading') {
await new Promise(resolve => {
document.addEventListener('DOMContentLoaded', resolve);
});
}
// 额外等待确保完全加载
await new Promise(resolve => setTimeout(resolve, 1000));
try {
const helper = new FixedSubsidyHelper();
await helper.init();
// 保存实例到全局,便于调试
window.subsidyHelper = helper;
console.log('✅ 脚本初始化完成,可以通过 window.subsidyHelper 访问实例');
} catch (error) {
console.error('❌ 脚本初始化失败:', error);
// 显示错误信息
const errorDiv = document.createElement('div');
errorDiv.style.cssText = `
position: fixed;
top: 10px;
left: 10px;
background: #ff4444;
color: white;
padding: 10px;
border-radius: 5px;
z-index: 10000;
font-family: Arial;
`;
errorDiv.innerHTML = `
脚本初始化失败
错误: ${error.message}
请刷新页面重试或查看控制台
`;
document.body.appendChild(errorDiv);
}
}
// 启动脚本
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeScript);
} else {
initializeScript();
}
})();