diff --git a/XboxAutoRegister-main/README.md b/XboxAutoRegister-main/README.md deleted file mode 100644 index ec7ef90..0000000 --- a/XboxAutoRegister-main/README.md +++ /dev/null @@ -1 +0,0 @@ -# XboxAutoRegister \ No newline at end of file diff --git a/XboxAutoRegister-main/calc_us_price.js b/XboxAutoRegister-main/calc_us_price.js deleted file mode 100644 index 1f31c73..0000000 --- a/XboxAutoRegister-main/calc_us_price.js +++ /dev/null @@ -1,209 +0,0 @@ -const readline = require('readline'); - -const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout -}); - -// 终极破甲器:手动追踪跳转,继承 Cookie,半路截取游戏 ID -async function resolveGameId(startUrl) { - let currentUrl = startUrl; - let cookies = {}; - - for (let i = 0; i < 7; i++) { // 最多追踪 7 层跳转 - try { - // 拼接继承的 Cookie - const cookieHeader = Object.entries(cookies).map(([k, v]) => `${k}=${v}`).join('; '); - - const response = await fetch(currentUrl, { - redirect: 'manual', // 关键:关闭自动跳转,改为我们手动一步步跟 - headers: { - 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36', - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', - 'Accept-Language': 'en-US,en;q=0.5', - 'Cookie': cookieHeader - } - }); - - // 继承服务器发下来的 Cookie,伪装得更像真人 - const setCookieHeader = response.headers.get('set-cookie'); - if (setCookieHeader) { - const parts = setCookieHeader.split(/,(?=\s*[a-zA-Z0-9_-]+\s*=)/); - for (const part of parts) { - const cookiePair = part.split(';')[0]; - const [key, ...val] = cookiePair.split('='); - if (key && val) cookies[key.trim()] = val.join('=').trim(); - } - } - - if (response.status >= 300 && response.status < 400) { - const location = response.headers.get('location'); - if (!location) break; - - const nextUrl = location.startsWith('http') ? location : new URL(location, currentUrl).href; - - // 解密 URL,剥开追踪网的层层包装 - let decodedUrl = nextUrl; - try { decodedUrl = decodeURIComponent(decodedUrl); } catch(e){} - try { decodedUrl = decodeURIComponent(decodedUrl); } catch(e){} - - // ⭐️ 半路截胡:只要在跳转链接里发现了 9 开头的 12 位代码,直接带走,不再往下跳! - const idMatch = decodedUrl.match(/(?:\/|id=|ProductId=|bigIds=)([9][A-Za-z0-9]{11})(?:[\/?#&'"]|$)/i); - if (idMatch) return idMatch[1].toUpperCase(); - - currentUrl = nextUrl; - } else if (response.status === 200) { - const htmlText = await response.text(); - - // 搜刮网页源码,防备 JS 动态跳转 - const htmlMatch = htmlText.match(/(?:\/|id=|ProductId=|bigIds=)([9][A-Za-z0-9]{11})(?:[\/?#&'"]|$)/i); - if (htmlMatch) return htmlMatch[1].toUpperCase(); - - // 检查 Meta Refresh 自动跳转 - const metaRefresh = htmlText.match(/]*http-equiv=["']refresh["'][^>]*content=["']\d+;\s*url=([^"']+)["']/i); - if (metaRefresh) { - currentUrl = metaRefresh[1].replace(/&/g, '&'); - if (!currentUrl.startsWith('http')) currentUrl = new URL(currentUrl, startUrl).href; - continue; - } - - // 检查 JS 自动跳转 - const jsRedirect = htmlText.match(/(?:window\.)?location(?:\.href)?\s*=\s*['"]([^'"]+)['"]/i); - if (jsRedirect) { - currentUrl = jsRedirect[1]; - if (!currentUrl.startsWith('http')) currentUrl = new URL(currentUrl, startUrl).href; - continue; - } - - break; - } else { - break; - } - } catch (e) { - break; - } - } - return null; -} - -// 核心查询逻辑 -async function getUSGameData(startUrl) { - try { - const urlObj = new URL(startUrl); - urlObj.searchParams.set('r', 'en-us'); - - let bigId = await resolveGameId(urlObj.toString()); - - if (!bigId) { - return { success: false, reason: "防爬虫拦截,未能从底层剥离出 12 位游戏代码" }; - } - - const apiUrl = `https://displaycatalog.mp.microsoft.com/v7.0/products?bigIds=${bigId}&market=US&languages=en-us&MS-CV=DUMMY.1`; - - const apiResponse = await fetch(apiUrl); - const data = await apiResponse.json(); - - if (!data.Products || data.Products.length === 0) { - return { success: false, reason: `成功获取 ID (${bigId}),但美区查无此游戏数据` }; - } - - const product = data.Products[0]; - const gameName = product.LocalizedProperties?.[0]?.ProductTitle || "未知游戏"; - - let finalPrice = null; - - if (!product.DisplaySkuAvailabilities || product.DisplaySkuAvailabilities.length === 0) { - return { success: false, name: gameName, reason: "该游戏没有销售规格 (无法购买)" }; - } - - // 智能找买断价 - for (const skuObj of product.DisplaySkuAvailabilities) { - if (skuObj.Sku && (skuObj.Sku.SkuType === 'full' || skuObj.Sku.SkuType === 'dlc' || skuObj.Sku.SkuType === 'consumable')) { - for (const avail of skuObj.Availabilities || []) { - if (avail.Actions && avail.Actions.includes('Purchase') && avail.OrderManagementData?.Price !== undefined) { - finalPrice = avail.OrderManagementData.Price.ListPrice; - break; - } - } - } - if (finalPrice !== null) break; - } - - if (finalPrice === null) { - for (const skuObj of product.DisplaySkuAvailabilities) { - for (const avail of skuObj.Availabilities || []) { - if (avail.Actions && avail.Actions.includes('Purchase') && avail.OrderManagementData?.Price !== undefined) { - finalPrice = avail.OrderManagementData.Price.ListPrice; - break; - } - } - if (finalPrice !== null) break; - } - } - - if (finalPrice === null) { - return { success: false, name: gameName, reason: "只有 XGP 订阅试玩或捆绑包专属,无单买价格" }; - } - - return { success: true, name: gameName, price: finalPrice }; - } catch (e) { - return { success: false, reason: `发生异常: ${e.message}` }; - } -} - -const inputUrls = []; - -console.log('🎮 请粘贴你的 Xbox 链接串 (支持包含回车的多行文本)。'); -console.log('💡 提示:粘贴完成后,请在【新的一行】按一次回车开始计算:\n'); - -rl.on('line', (line) => { - const trimmedLine = line.trim(); - if (trimmedLine === '') { - if (inputUrls.length > 0) { - rl.close(); - processUrls(inputUrls); - } - return; - } - const splitUrls = trimmedLine.split(/(?=https?:\/\/)/).filter(u => u.startsWith('http')); - inputUrls.push(...splitUrls); -}); - -async function processUrls(urls) { - console.log(`\n✅ 成功读取到 ${urls.length} 个链接,开始逐个查询美区价格...\n`); - - let totalPrice = 0; - let successCount = 0; - const failedDetails = []; - - for (let i = 0; i < urls.length; i++) { - const url = urls[i]; - process.stdout.write(`[${i + 1}/${urls.length}] 正在查询... `); - - const result = await getUSGameData(url); - - if (result.success) { - console.log(`✅ 成功 | ${result.name} | 现价: $${result.price}`); - totalPrice += result.price; - successCount++; - } else { - const namePart = result.name ? `[${result.name}] ` : ""; - console.log(`❌ 失败 | ${namePart}原因: ${result.reason}`); - failedDetails.push({ url, reason: result.reason, name: result.name }); - } - } - - console.log("\n================ 结算单 ================"); - console.log(`总计识别: ${urls.length} 个游戏`); - console.log(`成功查询: ${successCount} 个游戏`); - console.log(`美元总价: $${totalPrice.toFixed(2)}`); - console.log("========================================\n"); - - if (failedDetails.length > 0) { - console.log("⚠️ 以下链接需要手动核查:"); - failedDetails.forEach((f, idx) => { - const nameStr = f.name ? `游戏: ${f.name}\n ` : ""; - console.log(`${idx + 1}. ${nameStr}原因: ${f.reason}\n 链接: ${f.url}`); - }); - } -} \ No newline at end of file diff --git a/XboxAutoRegister-main/geckodriver.exe b/XboxAutoRegister-main/geckodriver.exe deleted file mode 100644 index 59b6a49..0000000 Binary files a/XboxAutoRegister-main/geckodriver.exe and /dev/null differ diff --git a/XboxAutoRegister-main/rotate.ps1 b/XboxAutoRegister-main/rotate.ps1 deleted file mode 100644 index 797c36c..0000000 --- a/XboxAutoRegister-main/rotate.ps1 +++ /dev/null @@ -1,60 +0,0 @@ -# ================= CONFIG ================= -$API_URL = "http://127.0.0.1:9090" -$SECRET = "8130899" -$GROUP = "Rotate" -# ========================================== - -# 1. Force UTF-8 Output -[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 - -Write-Host "1. Connecting to Clash..." -ForegroundColor Cyan - -# Use WebClient (Stable & Fixes Encoding) -$wc = New-Object System.Net.WebClient -$wc.Encoding = [System.Text.Encoding]::UTF8 - -try { - # URL - $ListUrl = "$API_URL/proxies/$GROUP" - - # === Step A: Get List === - # Add Auth Header - if ($SECRET -ne "") { $wc.Headers.Add("Authorization", "Bearer $SECRET") } - - $JsonContent = $wc.DownloadString($ListUrl) - - $JsonObj = $JsonContent | ConvertFrom-Json - $NodeList = $JsonObj.all - - if (!$NodeList -or $NodeList.Count -eq 0) { - throw "Error: Group [$GROUP] is empty!" - } - Write-Host " > Found $($NodeList.Count) nodes." -ForegroundColor Green - - # === Step B: Pick Random === - $Target = $NodeList | Get-Random - Write-Host "2. Switching to: $Target" -ForegroundColor Cyan - - # === Step C: Send Switch Command === - $Payload = @{ name = $Target } | ConvertTo-Json -Compress - - # 【Critical Fix】Clear headers to remove old Auth, preventing duplicate headers - $wc.Headers.Clear() - - # Re-add Headers correctly - $wc.Headers.Add("Content-Type", "application/json") - if ($SECRET -ne "") { $wc.Headers.Add("Authorization", "Bearer $SECRET") } - - # Send PUT - $Response = $wc.UploadString($ListUrl, "PUT", $Payload) - - Write-Host "3. [SUCCESS] Switched to: $Target" -ForegroundColor Green - -} catch { - Write-Host "==== ERROR ====" -ForegroundColor Red - Write-Host $_.Exception.Message -ForegroundColor Yellow - if ($_.Exception.InnerException) { - Write-Host "Detail: $($_.Exception.InnerException.Message)" -ForegroundColor Yellow - } - exit 1 -} \ No newline at end of file diff --git a/XboxAutoRegister-main/run_bot.py b/XboxAutoRegister-main/run_bot.py deleted file mode 100644 index 884f775..0000000 --- a/XboxAutoRegister-main/run_bot.py +++ /dev/null @@ -1,382 +0,0 @@ -from selenium import webdriver -from selenium.webdriver.firefox.service import Service -from selenium.webdriver.firefox.options import Options -from selenium.webdriver.common.by import By -from selenium.webdriver.support.ui import WebDriverWait -from selenium.webdriver.support import expected_conditions as EC -import subprocess -import time -import os - -# === 配置区域 === -INPUT_CSV = r'input\outlook账号_part_2.csv' # 原始输入文件 -TEMP_RETRY_CSV = r'output\temp_retry.csv' # 第一轮失败存放处(复活赛的输入) -FINAL_FAILED_CSV = r'output\failed.csv' # 最终失败文件 -SUCCESS_CSV = r'output\success.csv' # 成功文件 - -POWERSHELL_SCRIPT = r"E:\ClashScript\rotate.ps1" -GECKODRIVER_PATH = "geckodriver.exe" -FIREFOX_BINARY_PATH = r"C:\Program Files\Mozilla Firefox\firefox.exe" - - -# ================= 工具函数 ================= - -def rotate_ip(): - """切换IP""" - print(">>> [系统] 正在切换 IP (后台运行中)...") - try: - subprocess.run( - ["powershell.exe", "-ExecutionPolicy", "Bypass", "-File", POWERSHELL_SCRIPT], - check=True, - shell=True - ) - print(">>> [系统] IP 切换完成,等待网络恢复...") - time.sleep(2) - except subprocess.CalledProcessError as e: - print(f"!!! IP 切换失败: {e}") - - -def append_to_csv(file_path, email, password): - """追加写入一行 CSV""" - file_exists = os.path.exists(file_path) - try: - with open(file_path, 'a', encoding='utf-8') as f: - if not file_exists: - f.write("卡号\n") - f.write(f"{email}----{password}\n") - f.flush() - except Exception as e: - print(f"写入文件 {file_path} 失败: {e}") - - -def read_file_lines(file_path): - """读取文件所有行""" - if not os.path.exists(file_path): - return [] - try: - with open(file_path, 'r', encoding='utf-8') as f: - return f.readlines() - except UnicodeDecodeError: - try: - with open(file_path, 'r', encoding='gb18030') as f: - return f.readlines() - except: - return [] - - -def rewrite_source_file(file_path, lines): - """重写源文件(用于删除行)""" - try: - with open(file_path, 'w', encoding='utf-8') as f: - f.writelines(lines) - except Exception as e: - print(f"!!! 更新源文件失败: {e}") - - -def parse_account(line): - """解析账号密码""" - line = line.strip() - if not line or "卡号" in line: - return None, None - - email = "" - pwd = "" - # 支持 ---- 分割 - if "----" in line: - parts = line.split("----") - email = parts[0].strip() - if len(parts) > 1: - pwd = parts[1].strip() - # 支持 , 分割 - elif "," in line: - parts = line.split(",") - email = parts[0].strip() - if len(parts) > 1: - pwd = parts[1].strip() - - if email and pwd: - return email, pwd - return None, None - - -def count_valid_accounts(file_path): - """统计有效账号数""" - lines = read_file_lines(file_path) - count = 0 - for line in lines: - e, _ = parse_account(line) - if e: - count += 1 - return count - - -def login_process(driver, email, password): - """ - 业务逻辑:登录 Xbox - 返回: True(成功) / False(失败) - """ - print(f"=== 开始处理: {email} ===") - - try: - driver.get("https://www.xbox.com/en-us/auth/msa?action=logIn") - - # 1. 输入账号 - try: - WebDriverWait(driver, 30).until( - EC.visibility_of_element_located((By.ID, "usernameEntry")) - ).send_keys(email) - except: - pass - - time.sleep(1) - try: - driver.find_element(By.XPATH, "//button[@data-testid='primaryButton']").click() - except: - pass - - # 2. 输入密码 - WebDriverWait(driver, 30).until( - EC.visibility_of_element_located((By.NAME, "passwd")) - ).send_keys(password.strip()) - - time.sleep(1.5) - driver.find_element(By.XPATH, "//button[@data-testid='primaryButton']").click() - - # === 3. URL检测循环 === - print(">>> 进入 URL 监控模式...") - loop_start_time = time.time() - - while True: - if time.time() - loop_start_time > 60: - print(">>> URL 检测超时 (60s),强制下一步") - break - - try: - current_url = driver.current_url - - if "xbox.com" in current_url: - print(f"√√√ 直接跳转到了 Xbox 首页,成功!") - return True - - if "account.live.com" in current_url or "login.live.com" in current_url: - try: - # 处理跳过按钮 - skip_btns = driver.find_elements(By.ID, "iShowSkip") - if skip_btns and skip_btns[0].is_displayed(): - print(">>> 点击 '跳过'...") - skip_btns[0].click() - time.sleep(2) - continue - - # 处理常规确认按钮 - primary_btns = driver.find_elements(By.XPATH, "//button[@data-testid='primaryButton']") - if primary_btns and primary_btns[0].is_displayed(): - print(f">>> 检测到主按钮,点击确认...") - break - except: - pass - time.sleep(1) - else: - break - except: - break - - # === 4. 后续确认流程 === - clicked_yes = False - try: - yes_btn = WebDriverWait(driver, 10).until( - EC.element_to_be_clickable((By.XPATH, "//button[@data-testid='primaryButton']")) - ) - yes_btn.click() - clicked_yes = True - except: - pass - - if clicked_yes: - time.sleep(3) - - # 点击 "保存并继续" - print(" [关键] 等待 '保存并继续' (60s)...") - try: - save_btn = WebDriverWait(driver, 60).until( - EC.element_to_be_clickable((By.XPATH, "//button[contains(., '保存并继续')]")) - ) - save_btn.click() - time.sleep(3) - except: - print(f" [失败] 未找到 '保存并继续'") - return False - - # 检测成功标志 - print(" [关键] 等待 '可选诊断数据' (60s)...") - try: - WebDriverWait(driver, 60).until( - EC.presence_of_element_located((By.XPATH, "//h1[contains(., '可选诊断数据')]")) - ) - print(f"√√√√√√ 成功!账号 {email} 处理完毕!") - return True - - except: - print(f" [失败] 未检测到成功标志") - return False - - except Exception as e: - print(f"!!! 发生未知异常: {e}") - return False - - -def run_process_loop(source_file, success_output, fail_output, round_name): - """ - 通用处理循环: - 1. 读取 source_file - 2. 处理一个 -> 删一个 - 3. 成功 -> success_output - 4. 失败 -> fail_output - """ - print(f"\n========== 启动 {round_name} ==========") - print(f"输入: {source_file}") - print(f"失败将存入: {fail_output}") - - # 1. 统计总数 - total_count = count_valid_accounts(source_file) - if total_count == 0: - print(f"✨ {round_name} 无待处理账号,跳过。") - return 0 - - print(f"📊 {round_name} 待处理任务数: {total_count}") - - processed_count = 0 - fail_count = 0 - - while True: - # 2. 读取文件寻找下一个 - all_lines = read_file_lines(source_file) - - target_line_index = -1 - email = None - password = None - - for i, line in enumerate(all_lines): - e, p = parse_account(line) - if e and p: - target_line_index = i - email = e - password = p - break - - # 3. 如果找不到,说明本轮结束 - if target_line_index == -1: - print(f"\n🎉 {round_name} 结束!(进度: {processed_count}/{total_count})") - break - - processed_count += 1 - print(f"\n--------------------------------------------------") - print(f"🚀 [{round_name}] 进度: {processed_count}/{total_count} | 账号: {email}") - print(f"--------------------------------------------------") - - driver = None - try: - rotate_ip() # 换IP - - # 启动浏览器 - options = Options() - options.binary_location = FIREFOX_BINARY_PATH - options.add_argument("-headless") # 无头模式 - options.add_argument("--width=1920") - options.add_argument("--height=1080") - options.set_preference("general.useragent.override", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0") - options.add_argument("-private") - - # 性能优化参数 - options.set_preference("security.webauth.webauthn", False) - options.set_preference("security.webauth.u2f", False) - options.set_preference("signon.rememberSignons", False) - - service = Service(GECKODRIVER_PATH) - driver = webdriver.Firefox(service=service, options=options) - - # 执行 - is_success = login_process(driver, email, password) - - # 结果分流 - if is_success: - print(f"OOO 成功 -> 写入 {success_output}") - append_to_csv(success_output, email, password) - else: - print(f"XXX 失败 -> 写入 {fail_output}") - append_to_csv(fail_output, email, password) - fail_count += 1 - - except Exception as e: - print(f"!!! 运行异常: {e}") - append_to_csv(fail_output, email, password) - fail_count += 1 - - finally: - if driver: - try: - driver.quit() - except: - pass - - # 4. 【核心】从源文件移除该行(即时保存进度) - if target_line_index != -1 and target_line_index < len(all_lines): - check_e, _ = parse_account(all_lines[target_line_index]) - if check_e == email: - del all_lines[target_line_index] - rewrite_source_file(source_file, all_lines) - - time.sleep(2) - - # 循环结束,尝试删除源文件(如果已空) - final_lines = read_file_lines(source_file) - has_valid = any(parse_account(x)[0] for x in final_lines) - if not has_valid: - print(f"🗑️ {source_file} 已处理完毕,删除文件。") - try: - os.remove(source_file) - except: - pass - - return fail_count - - -def main(): - if not os.path.exists(FIREFOX_BINARY_PATH): - print(f"❌ 错误: 找不到 Firefox,请检查路径: {FIREFOX_BINARY_PATH}") - return - - # === 第一轮:初赛 === - # 输入: outlook账号.csv - # 失败去向: temp_retry.csv (临时复活池) - fail_round_1 = run_process_loop(INPUT_CSV, SUCCESS_CSV, TEMP_RETRY_CSV, "第一轮(初赛)") - - if fail_round_1 == 0: - print("\n🎉🎉🎉 第一轮全胜!无需复活赛。") - if os.path.exists(TEMP_RETRY_CSV): os.remove(TEMP_RETRY_CSV) - return - - # === 第二轮:复活赛 === - print(f"\n⚠️ 第一轮产生了 {fail_round_1} 个失败账号,准备进入复活赛...") - print("⏳ 等待 5 秒...") - time.sleep(5) - - # 输入: temp_retry.csv (第一轮的失败者) - # 失败去向: failed.csv (最终失败记录) - fail_round_2 = run_process_loop(TEMP_RETRY_CSV, SUCCESS_CSV, FINAL_FAILED_CSV, "第二轮(复活赛)") - - print(f"\n================ 最终统计 ================") - print(f"第一轮失败: {fail_round_1}") - print(f"第二轮救回: {fail_round_1 - fail_round_2}") - print(f"最终失败数: {fail_round_2}") - - if fail_round_2 == 0: - print("🎉 复活赛全部成功!") - if os.path.exists(FINAL_FAILED_CSV): os.remove(FINAL_FAILED_CSV) - else: - print(f"😭 仍有账号失败,请查看: {FINAL_FAILED_CSV}") - - -if __name__ == "__main__": - main() \ No newline at end of file diff --git a/XboxAutoRegister-main/split_csv.py b/XboxAutoRegister-main/split_csv.py deleted file mode 100644 index cb860c5..0000000 --- a/XboxAutoRegister-main/split_csv.py +++ /dev/null @@ -1,78 +0,0 @@ -import os -import shutil - - -def split_to_input_folder(input_file, rows_per_file=15): - """ - 将原始 CSV 切分并存入 ./input/ 文件夹,完成后删除原文件 - """ - target_dir = "input" - - # 1. 检查源文件 - if not os.path.exists(input_file): - print(f"❌ 错误:找不到源文件 '{input_file}'") - return - - # 2. 创建 input 文件夹(如果不存在) - if not os.path.exists(target_dir): - os.makedirs(target_dir) - print(f"📁 已创建目录: {target_dir}") - - # 3. 读取内容 - try: - try: - with open(input_file, 'r', encoding='utf-8') as f: - lines = f.readlines() - except UnicodeDecodeError: - with open(input_file, 'r', encoding='gb18030') as f: - lines = f.readlines() - except Exception as e: - print(f"❌ 读取文件失败: {e}") - return - - if len(lines) < 2: - print("⚠️ 文件中没有足够的账号数据。") - return - - # 提取表头和数据行 - header = lines[0] - data_lines = [l for l in lines[1:] if l.strip()] - total_accounts = len(data_lines) - - print(f"📂 发现 {total_accounts} 个账号,准备切分...") - - # 4. 开始切分并写入 input 文件夹 - file_count = 0 - success_count = 0 - - for i in range(0, total_accounts, rows_per_file): - file_count += 1 - chunk = data_lines[i: i + rows_per_file] - - # 生成输出路径,例如: input/outlook账号_part_1.csv - base_name = os.path.splitext(os.path.basename(input_file))[0] - output_filename = f"{base_name}_part_{file_count}.csv" - output_path = os.path.join(target_dir, output_filename) - - try: - with open(output_path, 'w', encoding='utf-8') as f: - f.write(header) - f.writelines(chunk) - success_count += 1 - print(f"✅ 已存入: {output_path} ({len(chunk)} 个账号)") - except Exception as e: - print(f"❌ 写入 {output_path} 失败: {e}") - return # 安全起见,失败则不删除原文件 - - # 5. 彻底删除原大文件 - if success_count > 0: - try: - os.remove(input_file) - print(f"\n🚀 分割完成!共生成 {success_count} 个文件并存入 '{target_dir}' 文件夹。") - print(f"🗑️ 原始文件 '{input_file}' 已删除。") - except Exception as e: - print(f"\n⚠️ 子文件已生成,但删除原文件失败: {e}") - - -if __name__ == "__main__": - split_to_input_folder('outlook账号.csv', rows_per_file=15) \ No newline at end of file