浏览器指纹生成

import random
import os
import json
import argparse

# 可复现随机种子(想每次都不一样,直接删除下面这行)
random.seed(42)

# ==================== UA 列表(62 个,2026 年最新真实风格) ====================
user_agents = [
    # Windows (Windows 10/11)
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36 Edg/127.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:127.0) Gecko/20100101 Firefox/127.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    # Windows 11 专属
    "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Windows NT 11.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",

    # macOS (Intel + Apple Silicon)
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
    # macOS Sequoia 专属
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 15_0_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",

    # Linux
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0",
    "Mozilla/5.0 (X11; Linux x86_64; rv:127.0) Gecko/20100101 Firefox/127.0",
    "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0",

    # Android (14/15)
    "Mozilla/5.0 (Linux; Android 14; SM-S928B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Mobile Safari/537.36",
    "Mozilla/5.0 (Linux; Android 14; Pixel 8 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Mobile Safari/537.36",
    "Mozilla/5.0 (Linux; Android 14; SM-G998B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",
    "Mozilla/5.0 (Linux; Android 15; Pixel 9 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Mobile Safari/537.36",
    "Mozilla/5.0 (Linux; Android 14; SM-F946B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Mobile Safari/537.36",  # Foldable

    # iOS (iPhone / iPad 17/18)
    "Mozilla/5.0 (iPhone; CPU iPhone OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPad; CPU OS 17_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPad; CPU OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
    "Mozilla/5.0 (iPhone16,2; CPU iPhone OS 18_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.1 Mobile/15E148 Safari/604.1",

    # 其他高仿真浏览器
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Brave/128.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Brave/129.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 OPR/114.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 OPR/115.0.0.0",
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Vivaldi/7.0.1234.55",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Vivaldi/7.0.1234.55",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36 Vivaldi/7.0.1234.55",
]

resolutions = [
    (1920, 1080, 1040, 1.0), (1366, 768, 728, 1.0), (2560, 1440, 1400, 1.0),
    (3840, 2160, 2120, 1.0), (5120, 2880, 2840, 1.0), (1512, 982, 942, 2.0),
    (3440, 1440, 1400, 1.0), (1728, 1117, 1077, 2.0),  # MacBook Pro
    (375, 667, 627, 3.0), (360, 640, 600, 2.0), (414, 896, 856, 3.0),
    (390, 844, 804, 3.0), (430, 932, 892, 3.0), (393, 852, 812, 3.0),  # iPhone 16
    (412, 915, 875, 2.75),  # Android Fold
]

timezones = [
    {"offset": -480, "name": "America/Los_Angeles", "dst": True},
    {"offset": 480, "name": "Asia/Shanghai", "dst": False},
    {"offset": 0, "name": "UTC", "dst": False},
    {"offset": -300, "name": "America/New_York", "dst": True},
    {"offset": 60, "name": "Europe/Paris", "dst": True},
    {"offset": 540, "name": "Asia/Tokyo", "dst": False},
    {"offset": 330, "name": "Asia/Kolkata", "dst": False},
]

webgl_options = [
    {"vendor": "Google Inc. (Intel)", "renderer": "ANGLE (Intel, Intel(R) UHD Graphics, Direct3D11 vs_5_0 ps_5_0)", "unmaskedVendor": "Intel Inc.", "unmaskedRenderer": "Intel(R) UHD Graphics"},
    {"vendor": "Google Inc. (NVIDIA)", "renderer": "ANGLE (NVIDIA, NVIDIA GeForce RTX 4060, Direct3D11 vs_5_0 ps_5_0)", "unmaskedVendor": "NVIDIA Corporation", "unmaskedRenderer": "NVIDIA GeForce RTX 4060"},
    {"vendor": "Apple Inc.", "renderer": "Apple GPU", "unmaskedVendor": "Apple Inc.", "unmaskedRenderer": "Apple M3 GPU"},
    {"vendor": "Google Inc. (AMD)", "renderer": "ANGLE (AMD, AMD Radeon RX 7600, Direct3D11 vs_5_0 ps_5_0)", "unmaskedVendor": "AMD", "unmaskedRenderer": "AMD Radeon RX 7600"},
    {"vendor": "Google Inc. (Intel)", "renderer": "ANGLE (Intel, Intel(R) Arc A770, Direct3D11 vs_5_0 ps_5_0)", "unmaskedVendor": "Intel Inc.", "unmaskedRenderer": "Intel(R) Arc A770"},
    {"vendor": "Google Inc. (NVIDIA)", "renderer": "ANGLE (NVIDIA, NVIDIA GeForce RTX 5090, Direct3D11 vs_5_0 ps_5_0)", "unmaskedVendor": "NVIDIA Corporation", "unmaskedRenderer": "NVIDIA GeForce RTX 5090"},
]

base_fonts = ["Arial", "Arial Black", "Calibri", "Helvetica", "Segoe UI", "Tahoma", "Times New Roman", "Verdana", "Microsoft YaHei", "SimSun"]

def rand_hash(length=64):
    return ''.join(random.choices('0123456789abcdef', k=length))

# ==================== 平台过滤(更精准) ====================
def filter_by_platform(ua_list, target_platform):
    if target_platform == 'all':
        return ua_list
    filtered = []
    for ua in ua_list:
        lower = ua.lower()
        if target_platform == 'windows' and 'windows' in lower:
            filtered.append(ua)
        elif target_platform == 'macos' and 'macintosh' in lower:
            filtered.append(ua)
        elif target_platform == 'linux' and 'linux' in lower and 'android' not in lower:
            filtered.append(ua)
        elif target_platform == 'android' and 'android' in lower:
            filtered.append(ua)
        elif target_platform == 'ios' and ('iphone' in lower or 'ipad' in lower):
            filtered.append(ua)
    return filtered if filtered else ua_list  # 兜底

# ==================== 鼠标轨迹模拟函数(保持不变) ====================
def generate_human_mouse_trajectory(width: int, height: int, num_points: int = 40):
    """生成类人鼠标移动轨迹:贝塞尔曲线 + 高斯噪声 + 速度/加速度模拟"""
    points = []
    x = random.randint(100, 300)
    y = random.randint(100, 300)
    points.append((x, y))
    for i in range(1, num_points):
        target_x = int(width * 0.7 + random.gauss(0, width * 0.12))
        target_y = int(height * 0.7 + random.gauss(0, height * 0.12))
        ctrl_x = x + (target_x - x) * 0.4 + random.gauss(0, 80)
        ctrl_y = y + (target_y - y) * 0.3 + random.gauss(0, 60)
        t = i / (num_points - 1)
        new_x = int((1-t)**3 * x + 3*(1-t)**2*t*ctrl_x + 3*(1-t)*t**2*target_x + t**3 * target_x)
        new_y = int((1-t)**3 * y + 3*(1-t)**2*t*ctrl_y + 3*(1-t)*t**2*target_y + t**3 * target_y)
        noise = 12 * (1 - t)
        new_x += int(random.gauss(0, noise))
        new_y += int(random.gauss(0, noise))
        x = max(0, min(width, new_x))
        y = max(0, min(height, new_y))
        points.append((x, y))
    return points

# ==================== WebRTC 完整伪装 JS(保持不变) ====================
WEBRTC_SPOOF_JS = """// WebRTC 完整伪装函数(2026最新版)
// 使用方法:在 Playwright / Puppeteer 中:await page.evaluate(() => spoofWebRTC('192.168.1.100', 54321));
function spoofWebRTC(fakeIP = '192.168.1.100', fakePort = 54321) {
  const OriginalRTCPeerConnection = window.RTCPeerConnection || window.webkitRTCPeerConnection;
  if (!OriginalRTCPeerConnection) return console.log('WebRTC 已不存在,无需伪装');

  window.RTCPeerConnection = function(config) {
    const pc = new OriginalRTCPeerConnection(config);
    const originalAddIce = pc.addIceCandidate;
    pc.addIceCandidate = function(candidate) {
      if (candidate && candidate.candidate) {
        candidate.candidate = candidate.candidate
          .replace(/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g, fakeIP)
          .replace(/raddr \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g, `raddr ${fakeIP}`)
          .replace(/rport \\d+/g, `rport ${fakePort}`);
      }
      return originalAddIce.apply(this, [candidate]);
    };
    const originalOnIce = pc.onicecandidate;
    pc.onicecandidate = function(event) {
      if (event.candidate) {
        event.candidate.candidate = event.candidate.candidate
          .replace(/\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g, fakeIP)
          .replace(/raddr \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g, `raddr ${fakeIP}`);
      }
      if (originalOnIce) originalOnIce.call(this, event);
    };
    const originalCreateOffer = pc.createOffer;
    pc.createOffer = function(options) {
      return originalCreateOffer.call(this, options).then(offer => {
        offer.sdp = offer.sdp.replace(/c=IN IP4 \\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}/g, `c=IN IP4 ${fakeIP}`);
        return offer;
      });
    };
    console.log(`✅ WebRTC 已完全伪装 | 假IP: ${fakeIP}:${fakePort}`);
    return pc;
  };
  Object.defineProperty(navigator, 'webRTCEnabled', { value: false, configurable: true });
  console.log('WebRTC 伪装完成');
}
"""

# ==================== 生成单个指纹 ====================
def generate_fingerprint(i, target_platform, ua_list):
    ua = random.choice(ua_list)
    res = random.choice(resolutions)
    width, height, avail_height, dpr = res
    tz = random.choice(timezones)
    wg = random.choice(webgl_options)
    
    device_mem = random.choice([4, 8, 16, 32])
    hw_conc = random.choice([4, 6, 8, 12, 16, 24])
    
    is_mobile = any(x in ua.lower() for x in ["mobile", "iphone", "android", "ipad"])
    max_touch = random.randint(5, 10) if is_mobile else 0
    
    canvas_fp = rand_hash(64)
    audio_fp = rand_hash(64)
    fonts_hash = rand_hash(32)
    
    lang = random.choice(["zh-CN", "en-US", "zh-TW", "ja-JP"])
    languages = [lang, lang.split('-')[0], "en-US", "en"]
    color_scheme = random.choice(["light", "dark"])
    
    lower_ua = ua.lower()
    if "macintosh" in lower_ua:
        platform = "macos"; nav_platform = "MacIntel"; vendor = "Apple Inc."
    elif "linux" in lower_ua and "android" not in lower_ua:
        platform = "linux"; nav_platform = "Linux x86_64"; vendor = "Google Inc."
    elif "android" in lower_ua:
        platform = "android"; nav_platform = "Linux armv81"; vendor = "Google Inc."
    elif "iphone" in lower_ua or "ipad" in lower_ua:
        platform = "ios"; nav_platform = "iPhone"; vendor = "Apple Inc."
    else:
        platform = "windows"; nav_platform = "Win32"; vendor = "Google Inc."
    
    fp_data = {
        "version": "1.0",
        "description": f"顶级高级浏览器指纹 {i:03d} - {platform.upper()} 平台 (v4.0)",
        "platform": platform,
        "fingerprint": {
            "navigator": {
                "userAgent": ua,
                "platform": nav_platform,
                "vendor": vendor,
                "appVersion": "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36",
                "appName": "Netscape",
                "appCodeName": "Mozilla",
                "product": "Gecko",
                "productSub": "20030107",
                "language": lang,
                "languages": languages,
                "deviceMemory": device_mem,
                "hardwareConcurrency": hw_conc,
                "maxTouchPoints": max_touch,
                "cookieEnabled": True,
                "onLine": True,
                "pdfViewerEnabled": True
            },
            "screen": {
                "width": width, "height": height, "availWidth": width, "availHeight": avail_height,
                "colorDepth": 24, "pixelDepth": 24, "devicePixelRatio": dpr,
                "orientation": {"type": "landscape-primary", "angle": 0}
            },
            "window": {
                "outerWidth": width, "outerHeight": height,
                "innerWidth": width - 16, "innerHeight": height - 117,
                "devicePixelRatio": dpr
            },
            "timezone": {"offset": tz["offset"], "name": tz["name"], "dst": tz["dst"]},
            "webgl": {
                "vendor": wg["vendor"], "renderer": wg["renderer"],
                "unmaskedVendor": wg["unmaskedVendor"], "unmaskedRenderer": wg["unmaskedRenderer"]
            },
            "canvas": {"fingerprint": canvas_fp},
            "audio": {"fingerprint": audio_fp},
            "fonts": {
                "list": base_fonts + random.sample(["Impact", "Courier New", "Georgia", "Palatino", "Lucida Grande"], 3),
                "hash": fonts_hash
            },
            "webrtc": {"enabled": False, "iceServers": []},
            "battery": {"charging": True, "level": 0.85},
            "plugins": [] if not is_mobile else ["Shockwave Flash", "Widevine Content Decryption Module"],
            "mimeTypes": [],
            "doNotTrack": random.choice(["1", "unspecified"]),
            "colorScheme": color_scheme,
            "reducedMotion": random.choice([True, False]),
            "reducedTransparency": False,
            "invertedColors": False,
            "forcedColors": False
        }
    }
    
    yaml_str = f"""# =============================================
# 顶级高级浏览器指纹 - YAML 格式 (v4.0)
# ID: {i:03d} | 平台: {platform.upper()} | UA: {ua[:70]}...
# 生成时间: 2026-04-21
# =============================================

version: "1.0"
description: "{fp_data['description']}"
platform: "{platform}"

fingerprint:
"""
    for section, data in fp_data["fingerprint"].items():
        yaml_str += f"  {section}:\n"
        if isinstance(data, dict):
            for k, v in data.items():
                if isinstance(v, (list, dict)):
                    yaml_str += f"    {k}: {json.dumps(v, ensure_ascii=False)}\n"
                else:
                    yaml_str += f"    {k}: {v}\n"
        else:
            yaml_str += f"    {section}: {data}\n"
    
    return fp_data, yaml_str

# ==================== 主程序 ====================
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="顶级高级浏览器指纹生成器 v4.0(62个UA + 更多平台变体)")
    parser.add_argument('--num', type=int, default=100, help='生成指纹数量 (默认 100)')
    parser.add_argument('--platform', type=str, default='all', choices=['all', 'windows', 'macos', 'linux', 'android', 'ios'], help='指定平台 (默认 all)')
    args = parser.parse_args()

    print(f"🚀 开始生成 {args.num} 个【v4.0 顶级版】浏览器指纹 | 平台: {args.platform.upper()}")
    
    filtered_ua = filter_by_platform(user_agents, args.platform)
    print(f"   已过滤 UA:{len(filtered_ua)} 个可用(总库 62 个)")
    
    output_dir = f"advanced_fingerprints_{args.platform}_v4"
    os.makedirs(output_dir, exist_ok=True)
    
    for i in range(1, args.num + 1):
        fp_data, yaml_content = generate_fingerprint(i, args.platform, filtered_ua)
        
        base_name = os.path.join(output_dir, f"browser_fingerprint_{i:03d}")
        
        with open(f"{base_name}.yaml", "w", encoding="utf-8") as f:
            f.write(yaml_content)
        with open(f"{base_name}.json", "w", encoding="utf-8") as f:
            json.dump(fp_data, f, indent=2, ensure_ascii=False)
        
        if i % 10 == 0 or i == args.num:
            print(f"✅ 已生成 {i:03d}/{args.num} 个指纹")
    
    # 生成辅助文件
    with open(os.path.join(output_dir, "mouse_trajectory_simulator.py"), "w", encoding="utf-8") as f:
        f.write('''# ==================== 鼠标轨迹模拟器 ====================
def generate_human_mouse_trajectory(width: int, height: int, num_points: int = 40):
    """生成类人鼠标移动轨迹:贝塞尔曲线 + 高斯噪声 + 速度/加速度模拟"""
    import random
    points = []
    x = random.randint(100, 300)
    y = random.randint(100, 300)
    points.append((x, y))
    for i in range(1, num_points):
        target_x = int(width * 0.7 + random.gauss(0, width * 0.12))
        target_y = int(height * 0.7 + random.gauss(0, height * 0.12))
        ctrl_x = x + (target_x - x) * 0.4 + random.gauss(0, 80)
        ctrl_y = y + (target_y - y) * 0.3 + random.gauss(0, 60)
        t = i / (num_points - 1)
        new_x = int((1-t)**3 * x + 3*(1-t)**2*t*ctrl_x + 3*(1-t)*t**2*target_x + t**3 * target_x)
        new_y = int((1-t)**3 * y + 3*(1-t)**2*t*ctrl_y + 3*(1-t)*t**2*target_y + t**3 * target_y)
        noise = 12 * (1 - t)
        new_x += int(random.gauss(0, noise))
        new_y += int(random.gauss(0, noise))
        x = max(0, min(width, new_x))
        y = max(0, min(height, new_y))
        points.append((x, y))
    return points

print("✅ 鼠标轨迹函数已加载")
''')
    
    with open(os.path.join(output_dir, "webrtc_spoof.js"), "w", encoding="utf-8") as f:
        f.write(WEBRTC_SPOOF_JS)
    
    print(f"\n🎉 生成完成!共 {args.num} 个指纹(v4.0)")
    print(f"📁 保存路径:{os.path.abspath(output_dir)}")
    print("   • *.yaml / *.json  → 指纹文件")
    print("   • mouse_trajectory_simulator.py → 鼠标轨迹代码")
    print("   • webrtc_spoof.js → WebRTC 伪装 JS")
    print("\n运行示例:")
    print("   python generate_fingerprints.py --num 300 --platform ios")
    print("   python generate_fingerprints.py --num 500 --platform all")
posted @ 2026-04-22 11:18  Timskt  阅读(5)  评论(0)    收藏  举报