Captcha Core Service

Complete core service for captcha processing

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.gf.qytechs.cn/scripts/530641/1558603/Captcha%20Core%20Service.js

// ==UserScript==
// @name         Captcha Core Service
// @namespace    http://your-namespace.com
// @version      1.0
// @description  Complete core service for captcha processing
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.0/jquery.min.js
// ==/UserScript==

class CaptchaCore {
  constructor() {
    this.elementRegistry = new Map();  // 已处理元素注册(不可用)表
    this.retryQueue = new Map();       // 重试队列
    this.currentProcessing = new Set(); // 正在处理队列
    
    // 初始化模块
    this.initializeDetectors();
    this.initializeErrorHandler();
  }

  // █████ 初始化模块 █████
  initializeDetectors() {
    // 通用验证码检测器
    this.detectors = {
      image: {
        selector: 'img[src*="captcha"], canvas.captcha',
        confidenceThreshold: 0.65
      },
      slide: {
        selector: '.slide-captcha, .geetest_',
        minWidth: 300
      },
      calculation: {
        selector: '.math-captcha',
        keywords: ['加', '减', '乘', '等于', '=?']
      }
    };

    // 绑定自动检测定时器
    setInterval(() => this.autoDetectCaptcha(), Config.RUNTIME.ELEMENT_DETECTION.SCAN_INTERVAL);
  }

  initializeErrorHandler() {
    window.addEventListener('unhandledrejection', event => {
      this.handleSystemError(event.reason);
    });
  }

  // █████ 主业务流程 █████
  async autoDetectCaptcha() {
    try {
      // 阶段1:元素检测
      const candidates = await this.detectCaptchaElements();
      
      // 阶段2:优先级排序
      const prioritized = this.sortByPriority(candidates);
      
      // 阶段3:并行处理
      await Promise.all(prioritized.map(async element => {
        if (this.shouldProcess(element)) {
          await this.processCaptcha(element);
        }
      }));
    } catch (error) {
      this.handleSystemError(error);
    }
  }

  // █████ 核心处理流程 █████
  async processCaptcha(element) {
    try {
      // 标记为处理中
      this.currentProcessing.add(element);

      // 步骤1:元素分类
      const captchaType = this.classifyCaptcha(element);
      
      // 步骤2:获取配置
      const config = this.getTypeConfig(captchaType);
      
      // 步骤3:图像处理
      const imageData = await this.prepareImageData(element, config);
      
      // 步骤4:API调用
      const result = await this.callCaptchaAPI(config, imageData);
      
      // 步骤5:结果处理
      await this.applyResult(element, result, config);
      
      // 步骤6:后续清理
      this.finalizeProcessing(element);

    } catch (error) {
      await this.handleProcessingError(element, error);
    } finally {
      this.currentProcessing.delete(element);
    }
  }

  // █████ 详细业务流程方法 █████
  async detectCaptchaElements() {
    const elements = [];
    
    // 图像验证码检测
    $(this.detectors.image.selector).each((i, el) => {
      if (this.isValidImageCaptcha(el)) elements.push(el);
    });

    // 滑块检测
    $(this.detectors.slide.selector).each((i, el) => {
      if (el.offsetWidth > this.detectors.slide.minWidth) elements.push(el);
    });

    // 计算题检测
    $(this.detectors.calculation.selector).each((i, el) => {
      if (this.containsMathKeywords(el)) elements.push(el);
    });

    return this.filterNewElements(elements);
  }

  async prepareImageData(element, config) {
    // 获取原始图像
    const rawImage = await this.loadImage(element);
    
    // 预处理流程
    return this.processImagePipeline(rawImage, {
      format: config.params.image_format || 'jpg',
      quality: config.params.quality || 0.8,
      resize: config.params.max_size ? {
        width: config.params.max_size[0],
        height: config.params.max_size[1]
      } : null,
      colorAdjust: config.params.color_correction || false
    });
  }

  async callCaptchaAPI(config, imageData) {
    const payload = this.buildPayload(config, imageData);
    
    // 带重试机制的请求
    return this.retryableRequest(() => 
      this.sendAPIRequest(payload), 
      config.retry || Config.DEFAULT_RETRY
    );
  }

  async applyResult(element, result, config) {
    switch(config.category) {
      case 'slide':
        await this.handleSlideResult(element, result, config);
        break;
        
      case 'calculation':
        this.fillCalculationResult(element, result);
        break;
        
      default:
        this.fillTextResult(element, result);
    }
  }

  // █████ 关键业务方法实现 █████
  classifyCaptcha(element) {
    // 元素特征分析
    const features = {
      hasSlider: !!element.querySelector('.slide-button'),
      colorCount: this.getColorComplexity(element),
      textDensity: this.calculateTextDensity(element)
    };

    // 分类决策树
    if (features.hasSlider) {
      return element.querySelector('.bg-image') ? 
        'SLIDE_DOUBLE' : 'SLIDE_SINGLE';
    }
    
    if (features.colorCount > 5 && features.textDensity < 0.3) {
      return 'COMPLEX_BG';
    }
    
    return this.defaultClassifier(element);
  }

  async handleSlideResult(element, result, config) {
    // 计算实际滑动距离
    const rawDistance = result.data.distance;
    const calibrated = config.calibration.formula(rawDistance);
    
    // 执行滑动操作
    await this.simulateSlide(
      element.querySelector('.slider'),
      calibrated,
      config.calibration.duration || 1000
    );
    
    // 结果验证
    await this.validateSlideSuccess(element);
  }

  simulateSlide(slider, distance, duration) {
    return new Promise(resolve => {
      const startX = slider.getBoundingClientRect().left;
      const steps = duration / 20;
      
      let currentStep = 0;
      const animate = () => {
        if (currentStep >= steps) {
          resolve();
          return;
        }
        
        const offset = (distance / steps) * currentStep;
        slider.style.transform = `translateX(${offset}px)`;
        
        currentStep++;
        requestAnimationFrame(animate);
      };
      
      animate();
    });
  }

  // █████ 错误处理系统 █████
  async handleProcessingError(element, error) {
    const errorConfig = Config.ERROR_CODES[error.code] || Config.ERROR_CODES.DEFAULT;
    
    // 记录错误日志
    this.logError({
      element,
      error,
      timestamp: Date.now(),
      retryCount: this.retryQueue.get(element)?.count || 0
    });

    // 执行重试逻辑
    if (errorConfig.retry) {
      await this.scheduleRetry(element, errorConfig);
      return;
    }

    // 执行回退策略
    if (errorConfig.fallback) {
      await this.processWithFallback(element, errorConfig.fallback);
    }
  }

  scheduleRetry(element, config) {
    return new Promise(resolve => {
      const retryInfo = this.retryQueue.get(element) || { count: 0 };
      
      if (retryInfo.count < config.max_attempts) {
        const delay = config.backoff[retryInfo.count] || config.backoff[0];
        
        setTimeout(async () => {
          await this.processCaptcha(element);
          resolve();
        }, delay);
        
        this.retryQueue.set(element, { 
          ...retryInfo, 
          count: retryInfo.count + 1 
        });
      }
    });
  }

  // █████ 辅助工具方法 █████
  getTypeConfig(type) {
    const config = Config.CAPTCHA_TYPES[type];
    if (!config) throw new Error(`Unsupported captcha type: ${type}`);
    return {
      ...config,
      category: this.getCategoryByType(type)
    };
  }

  getCategoryByType(type) {
    if (type.startsWith('SLIDE')) return 'slide';
    if (type.startsWith('MATH')) return 'calculation';
    return 'text';
  }

  shouldProcess(element) {
    return (
      !this.elementRegistry.has(element) &&
      !this.currentProcessing.has(element) &&
      this.isVisible(element)
    );
  }

  isVisible(element) {
    const style = window.getComputedStyle(element);
    return (
      style.visibility !== 'hidden' &&
      style.display !== 'none' &&
      element.offsetWidth > 0 &&
      element.offsetHeight > 0
    );
  }
}

// █████ 初始化入口 █████
(function() {
  'use strict';
  
  const captchaSystem = new CaptchaCore();
  
  // 暴露调试接口
  window.debugCaptcha = {
    reprocess: (selector) => {
      $(selector).each((i, el) => captchaSystem.processCaptcha(el));
    },
    getStats: () => ({
      processed: captchaSystem.elementRegistry.size,
      queue: captchaSystem.retryQueue.size
    })
  };
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址