更新IMAP邮件获取功能和账户保存格式
This commit is contained in:
59
ProxyPool.py
Normal file
59
ProxyPool.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import queue
|
||||
import time
|
||||
|
||||
class ProxyPool:
|
||||
"""代理IP池管理"""
|
||||
def __init__(self, proxy_file_path):
|
||||
self.proxy_queue = queue.Queue()
|
||||
self.success_queue = queue.Queue()
|
||||
self._load_proxies(proxy_file_path)
|
||||
|
||||
def _load_proxies(self, file_path):
|
||||
"""加载代理IP"""
|
||||
try:
|
||||
with open(file_path, "r") as file:
|
||||
proxy_ips = [line.strip() for line in file if line.strip()]
|
||||
self.proxy_count = len(proxy_ips)
|
||||
if self.proxy_count == 0:
|
||||
raise ValueError("代理文件为空")
|
||||
for proxy in proxy_ips:
|
||||
self.proxy_queue.put(proxy)
|
||||
except FileNotFoundError:
|
||||
raise FileNotFoundError(f"代理文件不存在: {file_path}")
|
||||
except Exception as e:
|
||||
raise Exception(f"加载代理文件失败: {str(e)}")
|
||||
|
||||
def get_proxy(self):
|
||||
"""获取代理IP"""
|
||||
max_retries = 12 # 最大等待时间60秒
|
||||
retries = 0
|
||||
|
||||
while retries < max_retries:
|
||||
try:
|
||||
if not self.success_queue.empty():
|
||||
return self.success_queue.get(block=False)
|
||||
|
||||
if not self.proxy_queue.empty():
|
||||
return self.proxy_queue.get(block=True, timeout=5)
|
||||
|
||||
if self.proxy_count == 0:
|
||||
raise ValueError("无可用代理")
|
||||
|
||||
retries += 1
|
||||
time.sleep(5)
|
||||
|
||||
except queue.Empty:
|
||||
continue
|
||||
except Exception as e:
|
||||
print(f"获取代理失败: {e}")
|
||||
time.sleep(1)
|
||||
|
||||
raise TimeoutError("获取代理超时")
|
||||
|
||||
def mark_success(self, proxy):
|
||||
"""标记成功的代理"""
|
||||
self.success_queue.put(proxy)
|
||||
|
||||
def mark_fail(self, proxy):
|
||||
"""标记失败的代理"""
|
||||
self.proxy_queue.put(proxy)
|
||||
83
PynoCaptchaSolver.py
Normal file
83
PynoCaptchaSolver.py
Normal file
@@ -0,0 +1,83 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Dict, Optional
|
||||
|
||||
from pynocaptcha import HcaptchaCracker
|
||||
from loguru import logger
|
||||
|
||||
|
||||
@dataclass
|
||||
class PynoCaptchaConfig:
|
||||
user_token: str
|
||||
sitekey: str = "8cf23430-f9c8-4aaa-9ba2-da32f65adf2e" # 默认值
|
||||
referer: str = "https://store.steampowered.com/join/"
|
||||
timeout: int = 60
|
||||
debug: bool = True
|
||||
user_agent: str = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36"
|
||||
|
||||
|
||||
class PynoCaptchaSolver:
|
||||
def __init__(self, config: PynoCaptchaConfig):
|
||||
self.config = config
|
||||
logger.debug(f"PynoCaptchaSolver 初始化 - 使用 PyNoCaptcha 库")
|
||||
|
||||
def solve_hcaptcha(self) -> Optional[Dict]:
|
||||
"""
|
||||
使用 PyNoCaptcha 库解决 HCaptcha 验证码
|
||||
|
||||
返回:
|
||||
成功时返回包含验证结果的字典,失败时返回None
|
||||
"""
|
||||
try:
|
||||
logger.debug(f"开始解决验证码 - sitekey: {self.config.sitekey}")
|
||||
logger.debug(f"使用User-Agent: {self.config.user_agent}")
|
||||
|
||||
# 创建验证码破解器
|
||||
cracker = HcaptchaCracker(
|
||||
user_token=self.config.user_token,
|
||||
sitekey=self.config.sitekey,
|
||||
referer=self.config.referer,
|
||||
user_agent=self.config.user_agent,
|
||||
debug=self.config.debug,
|
||||
timeout=self.config.timeout,
|
||||
)
|
||||
|
||||
# 破解验证码
|
||||
logger.debug("调用 PyNoCaptcha 进行破解")
|
||||
result = cracker.crack()
|
||||
|
||||
if result:
|
||||
logger.debug("验证码破解成功")
|
||||
return {
|
||||
"captcha_text": result.get("generated_pass_UUID"),
|
||||
"token": result.get("generated_pass_UUID"),
|
||||
"solution": result
|
||||
}
|
||||
else:
|
||||
logger.error("验证码破解失败")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"验证码破解过程中出错: {str(e)}")
|
||||
return None
|
||||
|
||||
|
||||
# 使用示例
|
||||
if __name__ == "__main__":
|
||||
# 配置
|
||||
config = PynoCaptchaConfig(
|
||||
user_token="cf169d36-0d62-45da-bff7-1eff42bbc4f3",
|
||||
sitekey="8cf23430-f9c8-4aaa-9ba2-da32f65adf2e",
|
||||
referer="https://store.steampowered.com/join/",
|
||||
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36"
|
||||
)
|
||||
|
||||
# 初始化求解器
|
||||
solver = PynoCaptchaSolver(config)
|
||||
|
||||
# 解决验证码
|
||||
result = solver.solve_hcaptcha()
|
||||
|
||||
if result:
|
||||
print(f"验证成功: {result['captcha_text'][:30]}...")
|
||||
else:
|
||||
print("验证失败")
|
||||
578
RegistrationGUIWithPynoV2.py
Normal file
578
RegistrationGUIWithPynoV2.py
Normal file
@@ -0,0 +1,578 @@
|
||||
import json
|
||||
import os
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import threading
|
||||
from tkinter import messagebox
|
||||
from tkinter import filedialog
|
||||
from ThreadManagerWithPyno import GUIThreadManagerWithPyno
|
||||
from PynoCaptchaSolver import PynoCaptchaConfig, PynoCaptchaSolver
|
||||
from SteamCaptchaHelper import SteamCaptchaHelper
|
||||
import time
|
||||
|
||||
# 配置日志
|
||||
from loguru import logger
|
||||
logger.add("steam_registration_pyno.log", rotation="10 MB")
|
||||
|
||||
class RegistrationGUIWithPynoV2:
|
||||
def __init__(self, root):
|
||||
self.root = root
|
||||
self.root.title("Steam注册 - PyNoCaptcha V2")
|
||||
self.root.geometry("800x800")
|
||||
self.root.minsize(800, 800) # 设置最小窗口大小
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(root)
|
||||
main_frame.pack(fill="both", expand=True, padx=10, pady=5)
|
||||
|
||||
# 顶部框架 - 包含所有输入配置
|
||||
top_frame = ttk.Frame(main_frame)
|
||||
top_frame.pack(fill="x", side="top", padx=5, pady=5)
|
||||
|
||||
# 创建配置框架
|
||||
config_frame = ttk.LabelFrame(top_frame, text="配置信息")
|
||||
config_frame.pack(fill="x", padx=5, pady=5)
|
||||
|
||||
# 加载默认配置
|
||||
self.script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
self.config_path = os.path.join(self.script_dir, 'config.json')
|
||||
self.config = self._load_config()
|
||||
|
||||
# 创建配置输入框
|
||||
self.config_vars = {}
|
||||
self._create_config_widgets(config_frame)
|
||||
|
||||
# 创建PyNoCaptcha配置框架
|
||||
captcha_frame = ttk.LabelFrame(top_frame, text="PyNoCaptcha配置")
|
||||
captcha_frame.pack(fill="x", padx=5, pady=5)
|
||||
|
||||
# 创建PyNoCaptcha配置输入框
|
||||
self.captcha_vars = {}
|
||||
self._create_captcha_widgets(captcha_frame)
|
||||
|
||||
# 创建Steam状态框架
|
||||
steam_frame = ttk.LabelFrame(top_frame, text="Steam验证状态")
|
||||
steam_frame.pack(fill="x", padx=5, pady=5)
|
||||
|
||||
# 添加Steam状态信息
|
||||
self.steam_status_var = tk.StringVar(value="未获取验证信息")
|
||||
self.steam_sitekey_var = tk.StringVar(value="未获取sitekey")
|
||||
self.steam_gid_var = tk.StringVar(value="未获取gid")
|
||||
|
||||
ttk.Label(steam_frame, text="状态:").grid(row=0, column=0, padx=5, pady=2, sticky="e")
|
||||
ttk.Label(steam_frame, textvariable=self.steam_status_var).grid(row=0, column=1, padx=5, pady=2, sticky="w")
|
||||
|
||||
ttk.Label(steam_frame, text="SiteKey:").grid(row=1, column=0, padx=5, pady=2, sticky="e")
|
||||
ttk.Label(steam_frame, textvariable=self.steam_sitekey_var).grid(row=1, column=1, padx=5, pady=2, sticky="w")
|
||||
|
||||
ttk.Label(steam_frame, text="GID:").grid(row=2, column=0, padx=5, pady=2, sticky="e")
|
||||
ttk.Label(steam_frame, textvariable=self.steam_gid_var).grid(row=2, column=1, padx=5, pady=2, sticky="w")
|
||||
|
||||
ttk.Button(steam_frame, text="刷新验证信息",
|
||||
command=self._refresh_steam_info).grid(row=3, column=0, columnspan=2, padx=5, pady=5)
|
||||
|
||||
# 创建文件选择框架
|
||||
files_frame = ttk.LabelFrame(top_frame, text="文件选择")
|
||||
files_frame.pack(fill="x", padx=5, pady=5)
|
||||
|
||||
# 邮箱文件选择
|
||||
self.email_path = tk.StringVar(value=os.path.join(self.script_dir, 'email_password.txt'))
|
||||
self._create_file_selector(files_frame, "邮箱文件:", self.email_path, 0)
|
||||
|
||||
# 代理文件选择
|
||||
self.proxy_path = tk.StringVar(value=os.path.join(self.script_dir, 'proxy_ips.txt'))
|
||||
self._create_file_selector(files_frame, "代理文件:", self.proxy_path, 1)
|
||||
|
||||
# 按钮框架 - 直接放在主界面上,任务列表上方
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.pack(fill="x", padx=5, pady=10)
|
||||
|
||||
# 添加开始按钮
|
||||
self.start_button = ttk.Button(
|
||||
button_frame,
|
||||
text="开始注册",
|
||||
command=self.start_registration,
|
||||
width=20
|
||||
)
|
||||
self.start_button.pack(side="left", padx=10, pady=5, expand=True)
|
||||
|
||||
# 添加停止按钮
|
||||
self.stop_button = ttk.Button(
|
||||
button_frame,
|
||||
text="停止注册",
|
||||
command=self.stop_registration,
|
||||
state="disabled",
|
||||
width=20
|
||||
)
|
||||
self.stop_button.pack(side="left", padx=10, pady=5, expand=True)
|
||||
|
||||
# 添加测试验证码按钮
|
||||
self.test_captcha_button = ttk.Button(
|
||||
button_frame,
|
||||
text="测试验证码",
|
||||
command=self.test_captcha,
|
||||
width=20
|
||||
)
|
||||
self.test_captcha_button.pack(side="left", padx=10, pady=5, expand=True)
|
||||
|
||||
# 中间框架 - 包含任务状态表格
|
||||
middle_frame = ttk.Frame(main_frame)
|
||||
middle_frame.pack(fill="both", expand=True, padx=5, pady=5)
|
||||
|
||||
# 创建任务列表框架
|
||||
task_frame = ttk.LabelFrame(middle_frame, text="任务状态")
|
||||
task_frame.pack(fill="both", expand=True, padx=5, pady=5)
|
||||
|
||||
# 创建表格框架
|
||||
table_frame = ttk.Frame(task_frame)
|
||||
table_frame.pack(fill="both", expand=True, padx=5, pady=5)
|
||||
|
||||
self.tree = ttk.Treeview(table_frame, columns=("邮箱", "状态", "账户名", "密码", "结果"), show="headings")
|
||||
|
||||
# 设置列头
|
||||
self.tree.heading("邮箱", text="邮箱")
|
||||
self.tree.heading("状态", text="状态")
|
||||
self.tree.heading("账户名", text="账户名")
|
||||
self.tree.heading("密码", text="密码")
|
||||
self.tree.heading("结果", text="结果")
|
||||
|
||||
# 设置列宽
|
||||
self.tree.column("邮箱", width=200)
|
||||
self.tree.column("状态", width=200)
|
||||
self.tree.column("账户名", width=100)
|
||||
self.tree.column("密码", width=100)
|
||||
self.tree.column("结果", width=100)
|
||||
|
||||
# 添加滚动条
|
||||
scrollbar = ttk.Scrollbar(table_frame, orient="vertical", command=self.tree.yview)
|
||||
self.tree.configure(yscrollcommand=scrollbar.set)
|
||||
|
||||
# 布局
|
||||
self.tree.pack(side="left", fill="both", expand=True)
|
||||
scrollbar.pack(side="right", fill="y")
|
||||
|
||||
# 存储线程状态
|
||||
self.thread_status = {}
|
||||
|
||||
# 存储Steam验证信息
|
||||
self.steam_data = None
|
||||
self.steam_helper = SteamCaptchaHelper()
|
||||
|
||||
# 添加进度控制变量
|
||||
self._stop_progress_update = False
|
||||
|
||||
# 添加版本标签
|
||||
version_label = ttk.Label(main_frame, text="PyNoCaptcha V2 版本", foreground="blue")
|
||||
version_label.pack(side="bottom", padx=5, pady=5)
|
||||
|
||||
def _refresh_steam_info(self):
|
||||
"""刷新Steam验证信息"""
|
||||
threading.Thread(target=self._refresh_steam_info_thread, daemon=True).start()
|
||||
|
||||
def _refresh_steam_info_thread(self):
|
||||
"""在新线程中刷新Steam验证信息"""
|
||||
try:
|
||||
self.steam_status_var.set("正在获取Steam验证信息...")
|
||||
self.steam_data = self.steam_helper.get_sitekey()
|
||||
|
||||
if self.steam_data:
|
||||
self.steam_status_var.set("获取验证信息成功")
|
||||
self.steam_sitekey_var.set(self.steam_data["sitekey"])
|
||||
self.steam_gid_var.set(self.steam_data["gid"])
|
||||
|
||||
# 更新验证码配置中的sitekey
|
||||
self.captcha_vars["pyno_sitekey"].set(self.steam_data["sitekey"])
|
||||
# 更新User-Agent
|
||||
self.captcha_vars["pyno_user_agent"].set(self.steam_helper.get_user_agent())
|
||||
else:
|
||||
self.steam_status_var.set("获取验证信息失败")
|
||||
except Exception as e:
|
||||
logger.error(f"刷新Steam信息出错: {str(e)}")
|
||||
self.steam_status_var.set(f"错误: {str(e)}")
|
||||
|
||||
def _load_config(self):
|
||||
"""加载配置文件"""
|
||||
try:
|
||||
with open(self.config_path, 'r') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"加载配置文件失败: {str(e)}")
|
||||
return {}
|
||||
|
||||
def _create_config_widgets(self, parent):
|
||||
"""创建配置输入控件"""
|
||||
config_items = [
|
||||
("protocol", "协议类型:", ["GRAPH", "IMAP", "POP3", "IMAP_OAUTH", "POP3_OAUTH"]),
|
||||
("ssl", "启用SSL:", ["True", "False"]),
|
||||
("email_url", "邮箱服务器:", None),
|
||||
("executornum", "线程数量:", None)
|
||||
]
|
||||
|
||||
for i, (key, label, options) in enumerate(config_items):
|
||||
ttk.Label(parent, text=label,width=10).grid(row=i, column=0, padx=5, pady=2, sticky="e")
|
||||
|
||||
if options:
|
||||
var = tk.StringVar(value=str(self.config.get(key, "")))
|
||||
widget = ttk.Combobox(parent, textvariable=var, values=options,width=50)
|
||||
else:
|
||||
var = tk.StringVar(value=str(self.config.get(key, "")))
|
||||
widget = ttk.Entry(parent, textvariable=var, width=50)
|
||||
|
||||
widget.grid(row=i, column=1, padx=5, pady=2, sticky="ew")
|
||||
self.config_vars[key] = var
|
||||
|
||||
def _create_captcha_widgets(self, parent):
|
||||
"""创建PyNoCaptcha配置输入控件"""
|
||||
captcha_items = [
|
||||
("pyno_user_token", "PyNoCaptcha API密钥:", None),
|
||||
("pyno_sitekey", "验证码网站Key:", None),
|
||||
("pyno_referer", "网站Referer:", None),
|
||||
("pyno_user_agent", "User-Agent:", None),
|
||||
("pyno_timeout", "超时时间(秒):", None),
|
||||
("pyno_debug", "调试模式:", ["True", "False"])
|
||||
]
|
||||
|
||||
for i, (key, label, options) in enumerate(captcha_items):
|
||||
ttk.Label(parent, text=label,width=12).grid(row=i, column=0, padx=5, pady=2, sticky="e")
|
||||
|
||||
if options:
|
||||
var = tk.StringVar(value=str(self.config.get(key, "True" if key == "pyno_debug" else "False")))
|
||||
widget = ttk.Combobox(parent, textvariable=var, values=options,width=50)
|
||||
else:
|
||||
default_value = ""
|
||||
if key == "pyno_sitekey":
|
||||
default_value = "8cf23430-f9c8-4aaa-9ba2-da32f65adf2e"
|
||||
elif key == "pyno_referer":
|
||||
default_value = "https://store.steampowered.com/join/"
|
||||
elif key == "pyno_timeout":
|
||||
default_value = "60"
|
||||
elif key == "pyno_user_agent":
|
||||
default_value = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36"
|
||||
|
||||
var = tk.StringVar(value=str(self.config.get(key, default_value)))
|
||||
widget = ttk.Entry(parent, textvariable=var, width=50)
|
||||
|
||||
widget.grid(row=i, column=1, padx=5, pady=2, sticky="ew")
|
||||
self.captcha_vars[key] = var
|
||||
|
||||
def _create_file_selector(self, parent, label, var, row):
|
||||
"""创建文件选择器"""
|
||||
parent.grid_columnconfigure(1, weight=1)
|
||||
ttk.Label(parent, text=label).grid(row=row, column=0, padx=5, pady=2, sticky="e")
|
||||
ttk.Entry(parent, textvariable=var).grid(row=row, column=1, padx=5, pady=2, sticky="ew")
|
||||
ttk.Button(parent, text="选择文件",
|
||||
command=lambda: var.set(filedialog.askopenfilename())
|
||||
).grid(row=row, column=2, padx=5, pady=2)
|
||||
|
||||
def update_status(self, email, status=None, account_name=None, password=None, result=None):
|
||||
"""更新任务状态
|
||||
|
||||
Args:
|
||||
email: 邮箱地址
|
||||
status: 当前状态
|
||||
account_name: 账户名
|
||||
password: 密码
|
||||
result: 结果
|
||||
"""
|
||||
try:
|
||||
# 防止值中包含taskId等敏感信息
|
||||
if status and isinstance(status, str) and 'taskId' in status:
|
||||
status = "正在处理验证码..."
|
||||
|
||||
if email not in self.thread_status:
|
||||
# 新建条目,将None替换为空字符串
|
||||
values = (
|
||||
email,
|
||||
status if status is not None else "",
|
||||
account_name if account_name is not None else "",
|
||||
password if password is not None else "",
|
||||
result if result is not None else ""
|
||||
)
|
||||
self.thread_status[email] = self.tree.insert("", "end", values=values)
|
||||
else:
|
||||
# 获取当前值
|
||||
current_values = list(self.tree.item(self.thread_status[email])['values'])
|
||||
|
||||
# 只更新非None的值
|
||||
if status is not None:
|
||||
current_values[1] = status
|
||||
if account_name is not None:
|
||||
current_values[2] = account_name
|
||||
if password is not None:
|
||||
current_values[3] = password
|
||||
if result is not None:
|
||||
current_values[4] = result
|
||||
|
||||
# 更新现有条目
|
||||
self.tree.item(self.thread_status[email], values=tuple(current_values))
|
||||
|
||||
# 更新界面
|
||||
self.root.update()
|
||||
except Exception as e:
|
||||
# 如果更新UI出错,至少在控制台输出信息
|
||||
print(f"更新界面时出错: {e}")
|
||||
|
||||
def get_completed_tasks(self):
|
||||
"""获取已经完成的任务列表"""
|
||||
completed_tasks = set()
|
||||
for email in self.thread_status:
|
||||
values = self.tree.item(self.thread_status[email])['values']
|
||||
if values[4]: # 检查result列是否有值
|
||||
completed_tasks.add(email)
|
||||
return completed_tasks
|
||||
|
||||
def _save_config(self):
|
||||
"""保存配置"""
|
||||
try:
|
||||
config = {}
|
||||
# 保存原有配置
|
||||
for key, var in self.config_vars.items():
|
||||
value = var.get()
|
||||
if key == "executornum":
|
||||
value = int(value)
|
||||
elif key == "ssl":
|
||||
value = value.lower() == "true"
|
||||
config[key] = value
|
||||
|
||||
# 保存PyNoCaptcha配置
|
||||
for key, var in self.captcha_vars.items():
|
||||
value = var.get()
|
||||
if key == "pyno_timeout":
|
||||
value = int(value)
|
||||
elif key == "pyno_debug":
|
||||
value = value.lower() == "true"
|
||||
config[key] = value
|
||||
|
||||
with open(self.config_path, 'w') as f:
|
||||
json.dump(config, f, indent=2)
|
||||
return True
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"保存配置失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def _validate_inputs(self):
|
||||
"""验证输入"""
|
||||
if not os.path.exists(self.email_path.get()):
|
||||
messagebox.showerror("错误", "邮箱文件不存在")
|
||||
return False
|
||||
|
||||
if not os.path.exists(self.proxy_path.get()):
|
||||
messagebox.showerror("错误", "代理文件不存在")
|
||||
return False
|
||||
|
||||
# 验证基本配置
|
||||
for key, var in self.config_vars.items():
|
||||
if not var.get().strip():
|
||||
messagebox.showerror("错误", f"请填写 {key} 配置项")
|
||||
return False
|
||||
|
||||
# 验证PyNoCaptcha配置
|
||||
required_captcha_keys = ["pyno_user_token"]
|
||||
for key in required_captcha_keys:
|
||||
if not self.captcha_vars[key].get().strip():
|
||||
messagebox.showerror("错误", f"请填写 {key} 配置项")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_captcha_config(self):
|
||||
"""获取PyNoCaptcha配置"""
|
||||
return PynoCaptchaConfig(
|
||||
user_token=self.captcha_vars["pyno_user_token"].get(),
|
||||
sitekey=self.captcha_vars["pyno_sitekey"].get(),
|
||||
referer=self.captcha_vars["pyno_referer"].get(),
|
||||
user_agent=self.captcha_vars["pyno_user_agent"].get(),
|
||||
timeout=int(self.captcha_vars["pyno_timeout"].get()),
|
||||
debug=self.captcha_vars["pyno_debug"].get().lower() == "true"
|
||||
)
|
||||
|
||||
def test_captcha(self):
|
||||
"""测试PyNoCaptcha验证码"""
|
||||
# 验证配置
|
||||
if not self.captcha_vars["pyno_user_token"].get().strip():
|
||||
messagebox.showerror("错误", "请先填写PyNoCaptcha API密钥")
|
||||
return
|
||||
|
||||
# 保存配置
|
||||
if not self._save_config():
|
||||
return
|
||||
|
||||
# 禁用测试按钮
|
||||
self.test_captcha_button.config(state="disabled")
|
||||
|
||||
# 在新线程中测试
|
||||
threading.Thread(target=self._test_captcha_thread, daemon=True).start()
|
||||
|
||||
def _test_captcha_thread(self):
|
||||
"""在新线程中测试PyNoCaptcha"""
|
||||
try:
|
||||
test_id = "测试PyNoCaptcha"
|
||||
self.update_status(test_id, status="正在准备验证码测试...")
|
||||
|
||||
# 首先获取动态sitekey
|
||||
self.update_status(test_id, status="正在获取Steam验证信息...")
|
||||
steam_data = self.steam_helper.get_sitekey()
|
||||
|
||||
if not steam_data:
|
||||
self.update_status(test_id, status="获取验证信息失败", result="失败")
|
||||
messagebox.showerror("错误", "获取Steam验证信息失败")
|
||||
return
|
||||
|
||||
# 更新界面上的sitekey
|
||||
self.steam_sitekey_var.set(steam_data["sitekey"])
|
||||
self.steam_gid_var.set(steam_data["gid"])
|
||||
self.steam_status_var.set("获取验证信息成功")
|
||||
|
||||
# 更新验证码配置
|
||||
self.captcha_vars["pyno_sitekey"].set(steam_data["sitekey"])
|
||||
self.captcha_vars["pyno_user_agent"].set(self.steam_helper.get_user_agent())
|
||||
self._save_config()
|
||||
|
||||
# 获取配置
|
||||
config = self.get_captcha_config()
|
||||
|
||||
# 创建求解器
|
||||
solver = PynoCaptchaSolver(config)
|
||||
|
||||
# 更新状态
|
||||
self.update_status(test_id, status="正在尝试解决验证码...")
|
||||
|
||||
# 解决验证码 - 每秒更新进度状态
|
||||
progress_thread = threading.Thread(
|
||||
target=self._update_captcha_progress,
|
||||
args=(test_id,),
|
||||
daemon=True
|
||||
)
|
||||
progress_thread.start()
|
||||
|
||||
# 解决验证码
|
||||
result = solver.solve_hcaptcha()
|
||||
|
||||
# 停止进度更新
|
||||
self._stop_progress_update = True
|
||||
|
||||
if not result:
|
||||
messagebox.showerror("失败", "验证码解决失败")
|
||||
self.update_status(test_id, status="验证码解决失败", result="失败")
|
||||
return
|
||||
|
||||
self.update_status(test_id, status="验证码解决成功")
|
||||
token_preview = result.get("captcha_text", "")[:30] + "..." if result.get("captcha_text") else "无令牌"
|
||||
self.update_status(test_id, status=f"验证码解决成功: {token_preview}")
|
||||
|
||||
# 尝试验证邮箱
|
||||
self.update_status(test_id, status="正在验证邮箱...")
|
||||
captcha_text = result.get("captcha_text")
|
||||
verify_result = self.steam_helper.verify_email(
|
||||
"749army@gmail.com",
|
||||
captcha_text,
|
||||
steam_data["init_id"],
|
||||
steam_data["gid"]
|
||||
)
|
||||
|
||||
if verify_result.get("success") == 1:
|
||||
messagebox.showinfo("成功", "验证邮箱成功!")
|
||||
self.update_status(test_id, status="验证成功", result="通过")
|
||||
else:
|
||||
error_msg = verify_result.get('details', verify_result.get('error', '未知错误'))
|
||||
messagebox.showerror("失败", f"验证邮箱失败: {error_msg}")
|
||||
self.update_status(test_id, status=f"验证失败: {error_msg}", result="失败")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"测试过程中出错: {str(e)}")
|
||||
messagebox.showerror("错误", f"测试过程中出错: {str(e)}")
|
||||
self.update_status("测试PyNoCaptcha", status=f"出错: {str(e)}", result="错误")
|
||||
finally:
|
||||
# 恢复按钮状态
|
||||
self.test_captcha_button.config(state="normal")
|
||||
# 确保停止进度更新
|
||||
self._stop_progress_update = True
|
||||
|
||||
def _update_captcha_progress(self, test_id):
|
||||
"""更新验证码进度显示"""
|
||||
self._stop_progress_update = False
|
||||
progress_chars = ["|", "/", "-", "\\"]
|
||||
i = 0
|
||||
while not self._stop_progress_update:
|
||||
self.update_status(test_id, status=f"正在尝试解决验证码... {progress_chars[i]}")
|
||||
time.sleep(0.5)
|
||||
i = (i + 1) % len(progress_chars)
|
||||
|
||||
def start_registration(self):
|
||||
"""启动注册流程"""
|
||||
try:
|
||||
if not self._validate_inputs(): # 添加输入验证
|
||||
return
|
||||
|
||||
if not self._save_config():
|
||||
return
|
||||
|
||||
if hasattr(self, 'manager') and self.manager:
|
||||
messagebox.showwarning("警告", "任务已在运行中")
|
||||
return
|
||||
|
||||
self.start_button.config(state="disabled")
|
||||
self.stop_button.config(state="normal")
|
||||
|
||||
threading.Thread(target=self._start_registration_thread,
|
||||
daemon=True,
|
||||
name="RegistrationThread").start()
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"启动失败: {str(e)}")
|
||||
self.start_button.config(state="normal")
|
||||
self.stop_button.config(state="disabled")
|
||||
|
||||
def _start_registration_thread(self):
|
||||
"""在新线程中启动注册"""
|
||||
try:
|
||||
completed_tasks = self.get_completed_tasks()
|
||||
|
||||
# 获取验证码配置并保存到config.json
|
||||
try:
|
||||
# 先获取最新的Steam验证信息
|
||||
steam_data = self.steam_helper.get_sitekey()
|
||||
if steam_data:
|
||||
self.steam_sitekey_var.set(steam_data["sitekey"])
|
||||
self.steam_gid_var.set(steam_data["gid"])
|
||||
self.steam_status_var.set("获取验证信息成功")
|
||||
|
||||
# 更新验证码配置
|
||||
self.captcha_vars["pyno_sitekey"].set(steam_data["sitekey"])
|
||||
self.captcha_vars["pyno_user_agent"].set(self.steam_helper.get_user_agent())
|
||||
|
||||
# 保存配置
|
||||
if not self._save_config():
|
||||
return
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"获取Steam验证信息失败: {str(e)}")
|
||||
return
|
||||
|
||||
# 使用PyNoCaptcha版本的GUIThreadManager
|
||||
self.manager = GUIThreadManagerWithPyno(
|
||||
self.config_path,
|
||||
self.email_path.get(),
|
||||
self.proxy_path.get(),
|
||||
self,
|
||||
completed_tasks
|
||||
)
|
||||
self.manager.start()
|
||||
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", str(e))
|
||||
finally:
|
||||
self.start_button.config(state="normal")
|
||||
self.stop_button.config(state="disabled")
|
||||
|
||||
def stop_registration(self):
|
||||
"""停止注册流程"""
|
||||
if hasattr(self, 'manager'):
|
||||
self.manager.stop()
|
||||
self.start_button.config(state="normal")
|
||||
self.stop_button.config(state="disabled")
|
||||
|
||||
if __name__ == "__main__":
|
||||
root = tk.Tk()
|
||||
gui = RegistrationGUIWithPynoV2(root)
|
||||
# 启动时自动刷新Steam信息
|
||||
threading.Thread(target=gui._refresh_steam_info_thread, daemon=True).start()
|
||||
root.mainloop()
|
||||
113
SteamCaptchaHelper.py
Normal file
113
SteamCaptchaHelper.py
Normal file
@@ -0,0 +1,113 @@
|
||||
import requests
|
||||
from lxml import etree
|
||||
from loguru import logger
|
||||
|
||||
class SteamCaptchaHelper:
|
||||
def __init__(self):
|
||||
# 使用标准的Steam请求头
|
||||
self.headers = {
|
||||
"Host": "store.steampowered.com",
|
||||
"X-Prototype-Version": "1.7",
|
||||
"sec-ch-ua-platform": "\"Windows\"",
|
||||
"sec-ch-ua": "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36",
|
||||
"Accept": "text/javascript, text/html, application/xml, text/xml, */*",
|
||||
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"Origin": "https://store.steampowered.com",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Referer": "https://store.steampowered.com/join/",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9"
|
||||
}
|
||||
self.session = requests.Session()
|
||||
self.session.headers.update(self.headers)
|
||||
|
||||
def get_sitekey(self):
|
||||
"""获取Steam网站的sitekey和其他必要信息"""
|
||||
try:
|
||||
# 获取初始页面
|
||||
logger.info("获取Steam注册页面...")
|
||||
url = "https://store.steampowered.com/join/"
|
||||
response = self.session.get(url, verify=False)
|
||||
html = etree.HTML(response.text)
|
||||
|
||||
# 提取init_id
|
||||
init_id = html.xpath('//input[@name="init_id"]/@value')
|
||||
if init_id:
|
||||
init_id = init_id[0]
|
||||
logger.info(f"获取init_id成功: {init_id}")
|
||||
else:
|
||||
logger.error("无法获取init_id")
|
||||
return None
|
||||
|
||||
# 刷新验证码获取sitekey
|
||||
logger.info("刷新验证码获取sitekey...")
|
||||
url = "https://store.steampowered.com/join/refreshcaptcha/"
|
||||
data = {"count": "1", "hcaptcha": "1"}
|
||||
response = self.session.post(url, data=data, verify=False)
|
||||
result = response.json()
|
||||
|
||||
gid = result.get("gid")
|
||||
sitekey = result.get("sitekey")
|
||||
|
||||
logger.info(f"获取gid成功: {gid}")
|
||||
logger.info(f"获取sitekey成功: {sitekey}")
|
||||
|
||||
return {
|
||||
"session": self.session,
|
||||
"init_id": init_id,
|
||||
"gid": gid,
|
||||
"sitekey": sitekey
|
||||
}
|
||||
except Exception as e:
|
||||
logger.error(f"获取sitekey过程中出错: {str(e)}")
|
||||
return None
|
||||
|
||||
def verify_email(self, email, captcha_text, init_id, gid):
|
||||
"""验证邮箱步骤"""
|
||||
try:
|
||||
logger.info(f"验证邮箱: {email}")
|
||||
url = "https://store.steampowered.com/join/ajaxverifyemail"
|
||||
|
||||
post_data = {
|
||||
"email": email,
|
||||
"captchagid": gid,
|
||||
"captcha_text": captcha_text,
|
||||
"elang": "6",
|
||||
"init_id": init_id,
|
||||
"guest": "false"
|
||||
}
|
||||
|
||||
response = self.session.post(url, data=post_data, verify=False)
|
||||
result = response.json()
|
||||
|
||||
logger.info(f"验证邮箱结果: {result}")
|
||||
|
||||
# 检查不同的响应类型
|
||||
# 1 表示成功
|
||||
# 17 可能是"创建Steam账户时发生错误"
|
||||
# 其他失败情况
|
||||
if 'success' not in result:
|
||||
result['success'] = 0
|
||||
result['error'] = "无效的响应"
|
||||
|
||||
return result
|
||||
except Exception as e:
|
||||
logger.error(f"验证邮箱过程中出错: {str(e)}")
|
||||
return {"success": 0, "error": str(e)}
|
||||
|
||||
def get_user_agent(self):
|
||||
"""返回Steam的用户代理"""
|
||||
return self.headers["User-Agent"]
|
||||
|
||||
# 使用示例
|
||||
if __name__ == "__main__":
|
||||
helper = SteamCaptchaHelper()
|
||||
data = helper.get_sitekey()
|
||||
if data:
|
||||
print(f"成功获取sitekey: {data['sitekey']}")
|
||||
else:
|
||||
print("获取sitekey失败")
|
||||
911
SteamRegistrationWithPyno.py
Normal file
911
SteamRegistrationWithPyno.py
Normal file
@@ -0,0 +1,911 @@
|
||||
import base64
|
||||
import imaplib
|
||||
import json
|
||||
import os
|
||||
import poplib
|
||||
import random
|
||||
import re
|
||||
import string
|
||||
import time
|
||||
import threading
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import tkinter as tk
|
||||
import email
|
||||
import email.header
|
||||
from email.parser import BytesParser
|
||||
from email.policy import default
|
||||
from PynoCaptchaSolver import PynoCaptchaConfig, PynoCaptchaSolver
|
||||
from loguru import logger
|
||||
from SteamCaptchaHelper import SteamCaptchaHelper
|
||||
|
||||
class SteamRegistrationWithPyno:
|
||||
"""Steam注册处理器 - 使用PyNoCaptcha解决验证码"""
|
||||
def __init__(self, config, proxy_pool):
|
||||
self.config = config
|
||||
self.proxy_pool = proxy_pool
|
||||
self.script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
self._file_lock = threading.Lock()
|
||||
self._session_local = threading.local()
|
||||
self.email_data = None
|
||||
self.session = None
|
||||
self.proxy_info = None
|
||||
self.cookie_str = None
|
||||
self.token = None
|
||||
self.access_token = None
|
||||
self.gid = None
|
||||
self.init_id = None
|
||||
self.sessionid = None
|
||||
self.gui = None
|
||||
self.running = True
|
||||
self._steam_gid = None
|
||||
self._steam_init_id = None
|
||||
self._steam_sitekey = None
|
||||
self.BASE_HEADERS = {
|
||||
"Accept": "*/*",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
|
||||
"User-Agent": "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",
|
||||
"Referer": "https://store.steampowered.com/join/",
|
||||
"Origin": "https://store.steampowered.com",
|
||||
"Connection": "keep-alive",
|
||||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"sec-ch-ua": '"Microsoft Edge";v="125"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"sec-ch-ua-platform": '"Windows"'
|
||||
}
|
||||
if not hasattr(self._session_local, 'session'):
|
||||
self._session_local.session = requests.Session()
|
||||
self._session_local.session.headers.update(self.BASE_HEADERS)
|
||||
|
||||
def set_gui(self, gui):
|
||||
self.gui = gui
|
||||
|
||||
def update_status(self, status, account_name=None, password=None, result=None):
|
||||
if self.gui:
|
||||
self.gui.update_status(self.email_data['email'], status, account_name, password, result)
|
||||
|
||||
def is_email_valid(self):
|
||||
"""验证邮箱有效性"""
|
||||
try:
|
||||
protocol = self.config['protocol']
|
||||
email_url = self.config['email_url']
|
||||
use_ssl = self.config['ssl']
|
||||
email = self.email_data['email']
|
||||
password = self.email_data['password']
|
||||
if protocol == "IMAP":
|
||||
server = imaplib.IMAP4_SSL(email_url) if use_ssl else imaplib.IMAP4(email_url)
|
||||
server.login(email, password)
|
||||
server.logout()
|
||||
elif protocol == "POP3":
|
||||
server = poplib.POP3_SSL(email_url) if use_ssl else poplib.POP3(email_url)
|
||||
server.user(email)
|
||||
server.pass_(password)
|
||||
server.quit()
|
||||
elif protocol == "GRAPH":
|
||||
self._get_access_token()
|
||||
if not self.access_token:
|
||||
raise ValueError("获取访问令牌失败")
|
||||
emails = self._graph_get_email()
|
||||
if emails is None:
|
||||
raise ValueError("获取邮件失败")
|
||||
elif protocol == "IMAP_OAUTH":
|
||||
self._get_access_token()
|
||||
if not self.access_token:
|
||||
raise ValueError("获取访问令牌失败")
|
||||
server = self._authenticate_oauth2()
|
||||
server.logout()
|
||||
elif protocol == "POP3_OAUTH":
|
||||
self._get_access_token()
|
||||
if not self.access_token:
|
||||
raise ValueError("获取访问令牌失败")
|
||||
server = self._authenticate_oauth2()
|
||||
server.quit()
|
||||
else:
|
||||
raise ValueError("不支持的协议类型")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"{email},邮箱验证失败: {e}")
|
||||
return False
|
||||
|
||||
def _get_access_token(self):
|
||||
"""获取OAuth访问令牌"""
|
||||
data = {
|
||||
'client_id': self.email_data['client_id'],
|
||||
'refresh_token': self.email_data['refresh_token'],
|
||||
'grant_type': 'refresh_token',
|
||||
}
|
||||
if self.config['protocol'] == 'GRAPH':
|
||||
data['scope'] = 'https://graph.microsoft.com/.default'
|
||||
response = requests.post(
|
||||
'https://login.microsoftonline.com/consumers/oauth2/v2.0/token',
|
||||
data=data
|
||||
)
|
||||
if response.status_code == 200:
|
||||
result = response.json()
|
||||
access_token = result.get('access_token')
|
||||
refresh_token = result.get('refresh_token')
|
||||
if refresh_token and refresh_token != self.email_data['refresh_token']:
|
||||
self.email_data['refresh_token'] = refresh_token
|
||||
self._update_refresh_token(refresh_token)
|
||||
self.access_token = access_token
|
||||
|
||||
def _authenticate_oauth2(self):
|
||||
"""OAuth2认证"""
|
||||
email = self.email_data['email']
|
||||
auth_string = f"user={email}\x01auth=Bearer {self.access_token}\x01\x01"
|
||||
auth_bytes = auth_string.encode('ascii')
|
||||
auth_b64 = base64.b64encode(auth_bytes).decode('ascii')
|
||||
|
||||
if self.config['protocol'] == "IMAP_OAUTH":
|
||||
server = imaplib.IMAP4_SSL('outlook.office365.com', 993)
|
||||
server.authenticate('XOAUTH2', lambda x: auth_string)
|
||||
return server
|
||||
elif self.config['protocol'] == "POP3_OAUTH":
|
||||
server = poplib.POP3_SSL('outlook.office365.com', 995)
|
||||
server._shortcmd('AUTH XOAUTH2')
|
||||
server._shortcmd(auth_b64)
|
||||
return server
|
||||
|
||||
def _graph_get_email(self):
|
||||
try:
|
||||
if not self.access_token:
|
||||
return None
|
||||
headers = {
|
||||
'Authorization': f'Bearer {self.access_token}',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
|
||||
params = {
|
||||
'$top': 5,
|
||||
'$select': 'subject,body,receivedDateTime,from,hasAttachments',
|
||||
'$orderby': 'receivedDateTime desc'
|
||||
}
|
||||
|
||||
response = requests.get('https://graph.microsoft.com/v1.0/me/messages', headers=headers,params=params)
|
||||
if response.status_code == 200:
|
||||
emails = response.json().get('value', [])
|
||||
return emails
|
||||
else:
|
||||
return None
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
def _update_refresh_token(self, refresh_token):
|
||||
"""更新refresh_token"""
|
||||
file_path = os.path.join(self.script_dir, 'email_password.txt')
|
||||
temp_path = os.path.join(self.script_dir, 'email_password.tmp')
|
||||
|
||||
with self._file_lock:
|
||||
try:
|
||||
with open(file_path, 'r') as f, open(temp_path, 'w') as temp:
|
||||
for line in f:
|
||||
parts = line.strip().split('----')
|
||||
if len(parts) == 4 and parts[0] == self.email_data['email']:
|
||||
parts[3] = refresh_token
|
||||
line = '----'.join(parts) + '\n'
|
||||
temp.write(line)
|
||||
os.replace(temp_path, file_path)
|
||||
except Exception as e:
|
||||
print(f"更新refresh_token失败: {e}")
|
||||
if os.path.exists(temp_path):
|
||||
os.remove(temp_path)
|
||||
|
||||
def _setup_session(self):
|
||||
"""设置代理会话"""
|
||||
if not self.proxy_info:
|
||||
raise ValueError("代理信息为空")
|
||||
|
||||
try:
|
||||
parts = self.proxy_info.split(":")
|
||||
if len(parts) != 4:
|
||||
raise ValueError("代理格式错误")
|
||||
|
||||
proxy_ip, proxy_port, username, password = parts
|
||||
# 验证端口是否为数字
|
||||
if not proxy_port.isdigit():
|
||||
raise ValueError("代理端口格式错误")
|
||||
|
||||
proxy_url = f"http://{username}:{password}@{proxy_ip}:{proxy_port}"
|
||||
self.session = self._session_local.session
|
||||
self.session.proxies = {
|
||||
"http": proxy_url,
|
||||
"https": proxy_url
|
||||
}
|
||||
# 设置超时
|
||||
self.session.timeout = (10, 30) # 连接超时10秒,读取超时30秒
|
||||
except Exception as e:
|
||||
print(f"设置代理会话失败: {e}")
|
||||
raise
|
||||
|
||||
def _refresh_steam_info(self):
|
||||
"""刷新Steam信息,获取最新的gid和sitekey"""
|
||||
try:
|
||||
# 使用SteamCaptchaHelper获取验证信息
|
||||
helper = SteamCaptchaHelper()
|
||||
steam_data = helper.get_sitekey()
|
||||
|
||||
if not steam_data:
|
||||
print("获取Steam验证信息失败")
|
||||
return None
|
||||
|
||||
# 提取数据
|
||||
self._steam_init_id = steam_data["init_id"]
|
||||
self._steam_gid = steam_data["gid"]
|
||||
self._steam_sitekey = steam_data["sitekey"]
|
||||
|
||||
# 使用SteamCaptchaHelper的session
|
||||
self.session = steam_data["session"]
|
||||
|
||||
# 输出获取信息
|
||||
print(f"获取init_id成功: {self._steam_init_id}")
|
||||
print(f"获取gid成功: {self._steam_gid}")
|
||||
print(f"获取sitekey成功: {self._steam_sitekey}")
|
||||
|
||||
# 更新配置中的sitekey
|
||||
if 'pyno_sitekey' in self.config:
|
||||
self.config['pyno_sitekey'] = self._steam_sitekey
|
||||
|
||||
# 确保配置中的user_agent与SteamCaptchaHelper一致
|
||||
if 'pyno_user_agent' in self.config:
|
||||
self.config['pyno_user_agent'] = helper.get_user_agent()
|
||||
|
||||
return {
|
||||
"gid": self._steam_gid,
|
||||
"sitekey": self._steam_sitekey,
|
||||
"init_id": self._steam_init_id,
|
||||
"session": self.session
|
||||
}
|
||||
except Exception as e:
|
||||
print(f"刷新Steam信息出错: {str(e)}")
|
||||
return None
|
||||
|
||||
def _get_captcha_with_pyno(self):
|
||||
"""使用PyNoCaptcha解决验证码"""
|
||||
try:
|
||||
print("正在使用PyNoCaptcha解决验证码...")
|
||||
|
||||
# 先从SteamCaptchaHelper获取标准UA
|
||||
helper = SteamCaptchaHelper()
|
||||
standard_user_agent = helper.get_user_agent()
|
||||
|
||||
# 确保sitekey是通过正确的UA获取的
|
||||
if not self._steam_sitekey or not self._steam_gid:
|
||||
print("需要先获取有效的sitekey和gid")
|
||||
steam_data = helper.get_sitekey()
|
||||
if steam_data:
|
||||
self._steam_sitekey = steam_data["sitekey"]
|
||||
self._steam_gid = steam_data["gid"]
|
||||
self._steam_init_id = steam_data["init_id"]
|
||||
self.session = steam_data["session"]
|
||||
else:
|
||||
print("无法获取有效的Steam验证信息")
|
||||
return None
|
||||
|
||||
# 创建PynoCaptcha配置,确保使用正确的UA
|
||||
config = PynoCaptchaConfig(
|
||||
user_token=self.config.get('pyno_user_token'),
|
||||
sitekey=self._steam_sitekey,
|
||||
referer="https://store.steampowered.com/join/",
|
||||
user_agent=standard_user_agent,
|
||||
timeout=self.config.get('pyno_timeout', 60),
|
||||
debug=self.config.get('pyno_debug', True)
|
||||
)
|
||||
|
||||
# 创建求解器
|
||||
solver = PynoCaptchaSolver(config)
|
||||
|
||||
# 解决验证码
|
||||
print("开始解决验证码...")
|
||||
result = solver.solve_hcaptcha()
|
||||
|
||||
if not result:
|
||||
print("PyNoCaptcha验证码解决失败")
|
||||
return None
|
||||
|
||||
print("PyNoCaptcha验证码解决成功")
|
||||
return result.get("captcha_text")
|
||||
|
||||
except Exception as e:
|
||||
print(f"PyNoCaptcha验证码解决出错: {str(e)}")
|
||||
return None
|
||||
|
||||
def _ajax_verify_email(self):
|
||||
"""发送邮箱验证请求"""
|
||||
# 使用从SteamCaptchaHelper获取的headers
|
||||
headers = {
|
||||
"Host": "store.steampowered.com",
|
||||
"X-Prototype-Version": "1.7",
|
||||
"sec-ch-ua-platform": "\"Windows\"",
|
||||
"sec-ch-ua": "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"X-Requested-With": "XMLHttpRequest",
|
||||
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36",
|
||||
"Accept": "text/javascript, text/html, application/xml, text/xml, */*",
|
||||
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||||
"Origin": "https://store.steampowered.com",
|
||||
"Sec-Fetch-Site": "same-origin",
|
||||
"Sec-Fetch-Mode": "cors",
|
||||
"Sec-Fetch-Dest": "empty",
|
||||
"Referer": "https://store.steampowered.com/join/",
|
||||
"Accept-Language": "zh-CN,zh;q=0.9"
|
||||
}
|
||||
|
||||
# 更新Cookie
|
||||
if self.cookie_str:
|
||||
headers["Cookie"] = self.cookie_str
|
||||
|
||||
print(f"使用gid: {self._steam_gid}")
|
||||
print(f"使用init_id: {self._steam_init_id}")
|
||||
|
||||
data = {
|
||||
"email": self.email_data['email'],
|
||||
"captchagid": self._steam_gid,
|
||||
"captcha_text": self.token,
|
||||
"elang": '6', # 使用中文
|
||||
"init_id": self._steam_init_id,
|
||||
"guest": "false"
|
||||
}
|
||||
|
||||
url = "https://store.steampowered.com/join/ajaxverifyemail"
|
||||
return self.session.post(
|
||||
url,
|
||||
headers=headers,
|
||||
data=data
|
||||
)
|
||||
|
||||
def _generate_random_account_name(self, length):
|
||||
"""生成随机账户名"""
|
||||
characters = string.ascii_lowercase + string.digits
|
||||
return ''.join(random.choice(characters) for _ in range(length))
|
||||
|
||||
def _generate_random_password(self, length):
|
||||
"""生成随机密码"""
|
||||
characters = string.ascii_letters + string.digits
|
||||
return ''.join(random.choice(characters) for _ in range(length))
|
||||
|
||||
def _check_account_name_availability(self, account_name):
|
||||
"""检查账户名可用性"""
|
||||
payload = {
|
||||
'accountname': account_name,
|
||||
'count': 1,
|
||||
'creationid': self.sessionid
|
||||
}
|
||||
|
||||
try:
|
||||
response = self.session.post(
|
||||
'https://store.steampowered.com/join/checkavail/',
|
||||
data=payload,
|
||||
headers=self.BASE_HEADERS
|
||||
)
|
||||
return response.json() if response.status_code == 200 else None
|
||||
except Exception as e:
|
||||
print(f"检查账户名失败: {e}")
|
||||
return None
|
||||
|
||||
def _check_password_availability(self, account_name, password):
|
||||
"""检查密码可用性"""
|
||||
payload = {
|
||||
'accountname': account_name,
|
||||
'password': password,
|
||||
'count': 1
|
||||
}
|
||||
|
||||
try:
|
||||
response = self.session.post(
|
||||
'https://store.steampowered.com/join/checkpasswordavail/',
|
||||
data=payload,
|
||||
headers=self.BASE_HEADERS
|
||||
)
|
||||
return response.json() if response.status_code == 200 else None
|
||||
except Exception as e:
|
||||
print(f"检查密码失败: {e}")
|
||||
return None
|
||||
|
||||
def _save_account(self, account_name, password, success):
|
||||
"""保存账户信息"""
|
||||
file_name = "accounts_succ.txt" if success else "accounts_fail.txt"
|
||||
file_path = os.path.join(self.script_dir, file_name)
|
||||
|
||||
with self._file_lock:
|
||||
try:
|
||||
with open(file_path, "a", encoding='utf-8') as file:
|
||||
# 新的固定格式:游戏帐:xxx 游戏密码:xxx 邮箱:xxx 邮箱密码:xxx webmail.evnmail.com
|
||||
if self.config['protocol'] in ["GRAPH", "IMAP_OAUTH", "POP3_OAUTH"]:
|
||||
# OAuth版本,包含额外的OAuth信息但不显示在保存的文件中
|
||||
save_data = (f"游戏帐:{account_name} 游戏密码:{password} 邮箱:{self.email_data['email']} "
|
||||
f"邮箱密码:{self.email_data['password']} webmail.evnmail.com\n")
|
||||
# 额外保存OAuth信息到专门的文件中
|
||||
oauth_path = os.path.join(self.script_dir, "accounts_oauth.txt")
|
||||
with open(oauth_path, "a", encoding='utf-8') as oauth_file:
|
||||
oauth_file.write(f"{account_name}----{password}----{self.email_data['email']}----"
|
||||
f"{self.email_data['password']}----{self.email_data['client_id']}----"
|
||||
f"{self.email_data['refresh_token']}\n")
|
||||
else:
|
||||
save_data = (f"游戏帐:{account_name} 游戏密码:{password} 邮箱:{self.email_data['email']} "
|
||||
f"邮箱密码:{self.email_data['password']} webmail.evnmail.com\n")
|
||||
file.write(save_data)
|
||||
except Exception as e:
|
||||
print(f"保存账户信息失败: {e}")
|
||||
|
||||
def _log_error(self,reason):
|
||||
self.update_status(f'{reason}',result='线程结束')
|
||||
"""记录错误"""
|
||||
error_path = os.path.join(self.script_dir, 'rgerror.txt')
|
||||
with self._file_lock:
|
||||
try:
|
||||
with open(error_path, 'a', encoding='utf-8') as file:
|
||||
# 根据协议类型保存不同格式的错误信息
|
||||
if self.config['protocol'] in ["GRAPH", "IMAP_OAUTH", "POP3_OAUTH"]:
|
||||
# 保存详细的OAuth错误信息到单独文件
|
||||
oauth_error_path = os.path.join(self.script_dir, 'oauth_error.txt')
|
||||
with open(oauth_error_path, 'a', encoding='utf-8') as oauth_file:
|
||||
oauth_file.write(f"{self.email_data['email']}----{self.email_data['password']}----"
|
||||
f"{self.email_data['client_id']}----{self.email_data['refresh_token']}\n")
|
||||
# 主错误文件使用标准格式
|
||||
error_data = f"邮箱:{self.email_data['email']} 邮箱密码:{self.email_data['password']} 错误原因:{reason} webmail.evnmail.com\n"
|
||||
else:
|
||||
error_data = f"邮箱:{self.email_data['email']} 邮箱密码:{self.email_data['password']} 错误原因:{reason} webmail.evnmail.com\n"
|
||||
file.write(error_data)
|
||||
except Exception as e:
|
||||
print(f"记录错误失败: {e}")
|
||||
|
||||
def _ajax_check_email_verified(self):
|
||||
"""检查邮箱验证状态"""
|
||||
if not self.sessionid:
|
||||
return False
|
||||
|
||||
data = {'creationid': self.sessionid}
|
||||
url = 'https://store.steampowered.com/join/ajaxcheckemailverified'
|
||||
headers = self.BASE_HEADERS.copy()
|
||||
headers.update({
|
||||
"cookie": self.cookie_str,
|
||||
})
|
||||
|
||||
start_time = time.time()
|
||||
verfy = False
|
||||
|
||||
while True:
|
||||
if time.time() - start_time > 180: # 超过3分钟退出循环
|
||||
self.update_status("邮箱验证超时")
|
||||
raise Exception("邮箱验证超时")
|
||||
response = self.session.post(url, data=data, headers=headers)
|
||||
if response.ok:
|
||||
success = response.json()
|
||||
if success['success'] == 1 or verfy:
|
||||
# 处理账户创建
|
||||
self.update_status("邮箱验证完成,提交注册")
|
||||
return self._create_account()
|
||||
else:
|
||||
print('等待邮箱验证')
|
||||
self.update_status("等待邮箱验证")
|
||||
if self._fetch_email_verification_url():
|
||||
time.sleep(5)
|
||||
verfy = True
|
||||
time.sleep(2)
|
||||
else:
|
||||
time.sleep(5)
|
||||
|
||||
def _fetch_email_verification_url(self):
|
||||
"""获取邮箱验证链接"""
|
||||
max_attempts = 6
|
||||
attempts = 0
|
||||
href = ''
|
||||
urls = []
|
||||
|
||||
def extract_urls_from_body(body, pattern):
|
||||
found_urls = re.findall(pattern, body)
|
||||
return [url.replace('&', '&').replace("=3D", "=").replace("=\r\n", "")
|
||||
.replace("\r\n", "").replace("=\n", "").replace("\n", "")
|
||||
for url in found_urls]
|
||||
|
||||
def decode_mime_words(text):
|
||||
"""解码MIME编码的文本"""
|
||||
if not text:
|
||||
return ""
|
||||
try:
|
||||
decoded = email.header.decode_header(text)
|
||||
return " ".join([
|
||||
(str(t[0], t[1] or 'utf-8') if isinstance(t[0], bytes) else str(t[0]))
|
||||
for t in decoded
|
||||
])
|
||||
except:
|
||||
return text
|
||||
|
||||
def get_body_text(msg):
|
||||
"""获取邮件正文文本内容"""
|
||||
if msg.is_multipart():
|
||||
# 如果邮件包含多个部分,递归处理
|
||||
text_parts = []
|
||||
for part in msg.get_payload():
|
||||
if part.get_content_type() == 'text/plain':
|
||||
charset = part.get_content_charset() or 'utf-8'
|
||||
try:
|
||||
text_parts.append(part.get_payload(decode=True).decode(charset))
|
||||
except:
|
||||
text_parts.append("[无法解码的内容]")
|
||||
elif part.is_multipart():
|
||||
# 递归处理多部分
|
||||
text_parts.append(get_body_text(part))
|
||||
return "\n".join(text_parts)
|
||||
else:
|
||||
# 单部分邮件
|
||||
content_type = msg.get_content_type()
|
||||
if content_type == 'text/plain':
|
||||
charset = msg.get_content_charset() or 'utf-8'
|
||||
try:
|
||||
return msg.get_payload(decode=True).decode(charset)
|
||||
except:
|
||||
return "[无法解码的内容]"
|
||||
else:
|
||||
return f"[内容类型: {content_type}]"
|
||||
|
||||
def process_emails(emails, pattern):
|
||||
for email in emails:
|
||||
body = email.get('body', {}).get('content', '')
|
||||
urls.extend(extract_urls_from_body(body, pattern))
|
||||
|
||||
def fetch_imap_emails():
|
||||
"""获取IMAP邮件中的验证链接"""
|
||||
local_urls = []
|
||||
try:
|
||||
self.update_status("正在连接IMAP服务器...")
|
||||
# 连接到IMAP服务器
|
||||
if self.config['ssl']:
|
||||
mail = imaplib.IMAP4_SSL(self.config['email_url'])
|
||||
else:
|
||||
mail = imaplib.IMAP4(self.config['email_url'])
|
||||
|
||||
# 登录
|
||||
self.update_status(f"正在登录邮箱...")
|
||||
mail.login(self.email_data['email'], self.email_data['password'])
|
||||
self.update_status("登录成功,开始获取邮件...")
|
||||
|
||||
# 只检查INBOX文件夹
|
||||
steam_verification_pattern = r'https://store\.steampowered\.com/account/newaccountverification\?[^\s"\'<>]+'
|
||||
|
||||
try:
|
||||
self.update_status("检查收件箱...")
|
||||
mail.select("INBOX")
|
||||
status, messages = mail.search(None, "ALL")
|
||||
if status != "OK" or not messages[0]:
|
||||
self.update_status("收件箱为空或无法访问")
|
||||
else:
|
||||
# 获取邮件ID列表,从最新的开始
|
||||
message_ids = messages[0].split()
|
||||
message_count = len(message_ids)
|
||||
self.update_status(f"找到 {message_count} 封邮件")
|
||||
|
||||
# 最多检查5封最新邮件
|
||||
check_count = min(5, message_count)
|
||||
message_ids = message_ids[-check_count:]
|
||||
message_ids.reverse() # 最新的邮件放在前面
|
||||
|
||||
for i, msg_id in enumerate(message_ids):
|
||||
self.update_status(f"正在检查邮件 {i+1}/{check_count}...")
|
||||
status, msg_data = mail.fetch(msg_id, "(RFC822)")
|
||||
if status != "OK":
|
||||
continue
|
||||
|
||||
# 解析邮件内容
|
||||
raw_email = msg_data[0][1]
|
||||
msg = email.message_from_bytes(raw_email, policy=default)
|
||||
|
||||
# 提取信息
|
||||
subject = decode_mime_words(msg["Subject"])
|
||||
|
||||
# 如果是Steam邮件,优先处理
|
||||
if "Steam" in subject:
|
||||
self.update_status(f"找到Steam邮件: {subject}")
|
||||
# 获取正文
|
||||
body = get_body_text(msg)
|
||||
|
||||
# 查找Steam验证链接
|
||||
found_urls = extract_urls_from_body(body, steam_verification_pattern)
|
||||
if found_urls:
|
||||
self.update_status(f"发现 {len(found_urls)} 个Steam验证链接")
|
||||
local_urls.extend(found_urls)
|
||||
else:
|
||||
self.update_status("不是Steam邮件,跳过")
|
||||
except Exception as e:
|
||||
self.update_status(f"处理邮件出错: {str(e)}")
|
||||
|
||||
# 尝试关闭连接
|
||||
try:
|
||||
mail.close()
|
||||
except:
|
||||
pass
|
||||
mail.logout()
|
||||
|
||||
except Exception as e:
|
||||
self.update_status(f"IMAP连接失败: {str(e)}")
|
||||
|
||||
return local_urls
|
||||
|
||||
def process_pop3(mail, pattern):
|
||||
num_messages = len(mail.list()[1])
|
||||
for i in range(num_messages):
|
||||
raw_email = b'\n'.join(mail.retr(i + 1)[1])
|
||||
text_body = raw_email.decode("utf-8")
|
||||
urls.extend(extract_urls_from_body(text_body, pattern))
|
||||
|
||||
while attempts < max_attempts:
|
||||
try:
|
||||
if self.config['protocol'] == "GRAPH":
|
||||
emails = self._graph_get_email()
|
||||
if emails:
|
||||
process_emails(emails, r'href="(https://store\.steampowered\.com/account/newaccountverification\?[^"]+)"')
|
||||
else:
|
||||
if self.config['protocol'] in ["IMAP", "IMAP_OAUTH"]:
|
||||
if self.config['protocol'] == "IMAP_OAUTH":
|
||||
self._get_access_token()
|
||||
if not self.access_token:
|
||||
attempts += 1
|
||||
time.sleep(5)
|
||||
continue
|
||||
mail = self._authenticate_oauth2()
|
||||
else:
|
||||
# 使用改进的IMAP处理
|
||||
self.update_status("开始获取邮件...")
|
||||
imap_urls = fetch_imap_emails()
|
||||
urls.extend(imap_urls)
|
||||
|
||||
elif self.config['protocol'] in ["POP3", "POP3_OAUTH"]:
|
||||
if self.config['protocol'] == "POP3_OAUTH":
|
||||
self._get_access_token()
|
||||
if not self.access_token:
|
||||
attempts += 1
|
||||
time.sleep(5)
|
||||
continue
|
||||
mail = self._authenticate_oauth2()
|
||||
else:
|
||||
mail = poplib.POP3_SSL(self.config['email_url']) if self.config['ssl'] else poplib.POP3(self.config['email_url'])
|
||||
mail.user(self.email_data['email'])
|
||||
mail.pass_(self.email_data['password'])
|
||||
process_pop3(mail, r'https://store\.steampowered\.com/account/newaccountverification\?stoken=3D[^\n]*\n[^\n]*\n[^\n]*\n\n\n')
|
||||
mail.quit()
|
||||
|
||||
# 检查验证链接
|
||||
for url in urls:
|
||||
self.update_status(f"找到可能的验证链接,检查匹配...")
|
||||
parsed_url = urlparse(url)
|
||||
query_string = parsed_url.query
|
||||
params = parse_qs(query_string)
|
||||
creationid = params.get('creationid')
|
||||
if creationid and creationid[0] == self.sessionid:
|
||||
href = url
|
||||
break
|
||||
|
||||
if href:
|
||||
self.update_status("找到匹配的验证链接,正在验证...")
|
||||
return self._verify_email_link(href)
|
||||
else:
|
||||
self.update_status("未找到匹配的验证链接,等待5秒后重试...")
|
||||
attempts += 1
|
||||
time.sleep(5)
|
||||
|
||||
except Exception as e:
|
||||
self.update_status(f"邮件处理错误: {str(e)}")
|
||||
attempts += 1
|
||||
time.sleep(5)
|
||||
|
||||
if attempts >= max_attempts:
|
||||
self.update_status("达到最大尝试次数,未能成功获取邮件或链接")
|
||||
return False
|
||||
|
||||
def _verify_email_link(self, href):
|
||||
"""验证邮箱链接"""
|
||||
headers = self.BASE_HEADERS.copy()
|
||||
headers.update({
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||
"Upgrade-Insecure-Requests": "1"
|
||||
})
|
||||
try:
|
||||
response = self.session.get(href, headers=headers)
|
||||
soup = BeautifulSoup(response.content, "html.parser")
|
||||
error_div = soup.find("div", class_="newaccount_email_verified_text error")
|
||||
|
||||
if error_div:
|
||||
print('验证失败')
|
||||
return False
|
||||
print("验证完成")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"验证链接访问失败: {e}")
|
||||
return False
|
||||
|
||||
def _create_account(self):
|
||||
"""创建Steam账户"""
|
||||
# 生成随机账户名和密码
|
||||
account_name = self._generate_random_account_name(random.randint(8, 12))
|
||||
|
||||
# 检查账户名可用性
|
||||
result = self._check_account_name_availability(account_name)
|
||||
if result:
|
||||
if result['bAvailable']:
|
||||
print(f"账户名可用: {account_name}")
|
||||
else:
|
||||
print("账户名不可用")
|
||||
if 'rgSuggestions' in result and result['rgSuggestions']:
|
||||
print("使用建议的账户名:", result['rgSuggestions'][0])
|
||||
account_name = result['rgSuggestions'][0]
|
||||
else:
|
||||
raise Exception("无法获取可用的账户名")
|
||||
else:
|
||||
raise Exception("账户名检查失败")
|
||||
|
||||
# 生成并检查密码
|
||||
while True:
|
||||
password = self._generate_random_password(random.randint(8, 12))
|
||||
password_result = self._check_password_availability(account_name, password)
|
||||
if password_result and password_result['bAvailable']:
|
||||
print(f"密码可用: {password}")
|
||||
break
|
||||
print("密码不可用,重新生成")
|
||||
|
||||
# 创建账户
|
||||
self.update_status("创建账户",account_name=account_name,password=password)
|
||||
self._create_steam_account(account_name, password)
|
||||
return True
|
||||
|
||||
def _create_steam_account(self, account_name, password):
|
||||
"""提交Steam账户创建请求"""
|
||||
data = {
|
||||
'accountname': account_name,
|
||||
'password': password,
|
||||
'count': 0,
|
||||
'lt': 1,
|
||||
'creation_sessionid': self.sessionid,
|
||||
'embedded_appid': 0,
|
||||
'guest': False
|
||||
}
|
||||
headers = self.BASE_HEADERS.copy()
|
||||
headers.update({
|
||||
"Cookie": self.cookie_str,
|
||||
"X-Requested-With": "XMLHttpRequest"
|
||||
})
|
||||
try:
|
||||
response = self.session.post(
|
||||
'https://store.steampowered.com/join/createaccount/',
|
||||
data=data,
|
||||
headers=headers
|
||||
)
|
||||
if response.ok:
|
||||
result = response.json()
|
||||
print(f'{account_name} 提交注册完成')
|
||||
self.update_status('提交注册完成',account_name=account_name,password=password,result=result['bSuccess'])
|
||||
self._save_account(account_name, password, result['bSuccess'])
|
||||
else:
|
||||
raise Exception(f'创建账户请求失败: {response.status_code}')
|
||||
except Exception as e:
|
||||
print(f'创建账户时出错: {str(e)}')
|
||||
raise
|
||||
|
||||
def main(self, email_data, retries=30):
|
||||
"""主处理函数"""
|
||||
main_retry_count = 0
|
||||
self.email_data = email_data
|
||||
if not self.is_email_valid():
|
||||
self._log_error("邮箱验证失败")
|
||||
return
|
||||
while main_retry_count < retries:
|
||||
try:
|
||||
if not self.running:
|
||||
self.update_status("任务已停止")
|
||||
break
|
||||
|
||||
# 设置代理(其他功能仍然需要代理)
|
||||
self.proxy_info = self.proxy_pool.get_proxy()
|
||||
self._setup_session()
|
||||
|
||||
# 先使用SteamCaptchaHelper获取验证信息,它使用正确的User-Agent
|
||||
self.update_status("获取Steam验证信息")
|
||||
helper = SteamCaptchaHelper()
|
||||
|
||||
# 如果有代理,设置到helper的session
|
||||
if hasattr(self.session, 'proxies') and self.session.proxies:
|
||||
helper.session.proxies = self.session.proxies
|
||||
|
||||
steam_data = helper.get_sitekey()
|
||||
if not steam_data:
|
||||
self.update_status("获取Steam验证信息失败,重试")
|
||||
raise Exception("获取Steam验证信息失败")
|
||||
|
||||
# 提取并保存验证信息
|
||||
self._steam_init_id = steam_data["init_id"]
|
||||
self._steam_gid = steam_data["gid"]
|
||||
self._steam_sitekey = steam_data["sitekey"]
|
||||
|
||||
# 使用helper的session
|
||||
self.session = steam_data["session"]
|
||||
|
||||
# 设置cookie
|
||||
self.cookie_str = "timezoneOffset=28800,0; Steam_Language=english; "
|
||||
cookies = self.session.cookies.get_dict()
|
||||
if cookies:
|
||||
self.cookie_str += '; '.join([f"{k}={v}" for k, v in cookies.items()])
|
||||
|
||||
# 使用PyNoCaptcha解决验证码
|
||||
self.update_status("使用PyNoCaptcha进行人机验证")
|
||||
self.token = self._get_captcha_with_pyno()
|
||||
if not self.token:
|
||||
self.update_status("验证码解决失败,重试")
|
||||
raise Exception("验证码解决失败")
|
||||
self.update_status("验证码解决成功")
|
||||
|
||||
# 提交邮箱验证
|
||||
self.update_status("提交注册验证")
|
||||
response = self._ajax_verify_email()
|
||||
|
||||
# 处理响应
|
||||
try:
|
||||
resp_json = response.json()
|
||||
success = resp_json.get('success', 0)
|
||||
details = resp_json.get('details', '')
|
||||
self.update_status(f'提交结果:状态={success}, 详情={details}')
|
||||
|
||||
if success != 1:
|
||||
self.update_status(f"验证未通过: {details}", result="失败")
|
||||
raise Exception(f"验证未通过: {details}")
|
||||
|
||||
# 获取sessionid
|
||||
self.sessionid = resp_json.get('sessionid')
|
||||
if not self.sessionid:
|
||||
self.update_status("未能获取sessionid", result="失败")
|
||||
raise Exception("未能获取sessionid")
|
||||
|
||||
# 进行邮箱验证
|
||||
self.update_status("等待邮箱验证")
|
||||
self._ajax_check_email_verified()
|
||||
|
||||
# 成功完成
|
||||
self.session.close()
|
||||
self.proxy_pool.mark_success(self.proxy_info)
|
||||
self.proxy_info = None
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
self.update_status(f"处理响应出错: {str(e)}")
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
if not self.running:
|
||||
self.update_status("任务已停止")
|
||||
break
|
||||
|
||||
# 安全地打印错误,避免泄露敏感信息
|
||||
error_msg = str(e)
|
||||
if len(error_msg) > 50:
|
||||
error_msg = error_msg[:50] + "..."
|
||||
self.update_status(f"出错: {error_msg}")
|
||||
|
||||
# 清理资源
|
||||
if self.session:
|
||||
try:
|
||||
self.session.close()
|
||||
except:
|
||||
pass
|
||||
if self.proxy_info:
|
||||
self.proxy_pool.mark_fail(self.proxy_info)
|
||||
self.proxy_info = None
|
||||
|
||||
# 增加重试计数
|
||||
main_retry_count += 1
|
||||
time.sleep(2)
|
||||
|
||||
# 达到最大重试次数
|
||||
if main_retry_count >= retries:
|
||||
self._log_error("达到最大重试次数")
|
||||
finally:
|
||||
# 确保资源被释放
|
||||
if self.session:
|
||||
try:
|
||||
self.session.close()
|
||||
except:
|
||||
pass
|
||||
if self.proxy_info:
|
||||
self.proxy_pool.mark_fail(self.proxy_info)
|
||||
self.proxy_info = None
|
||||
155
ThreadManagerWithPyno.py
Normal file
155
ThreadManagerWithPyno.py
Normal file
@@ -0,0 +1,155 @@
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
from ProxyPool import ProxyPool
|
||||
from SteamRegistrationWithPyno import SteamRegistrationWithPyno
|
||||
|
||||
|
||||
class ThreadManagerWithPyno:
|
||||
"""线程管理器 - 使用PyNoCaptcha版本"""
|
||||
def __init__(self, config_path, email_file_path, proxy_file_path):
|
||||
self.config = self._load_config(config_path)
|
||||
self._validate_config()
|
||||
self.proxy_pool = ProxyPool(proxy_file_path)
|
||||
self.email_file = email_file_path
|
||||
self.executor = ThreadPoolExecutor(max_workers=self.config['executornum'])
|
||||
self._registration_local = threading.local()
|
||||
self._running = True
|
||||
self._registrations = set()
|
||||
self._registrations_lock = threading.Lock()
|
||||
|
||||
def _validate_config(self):
|
||||
"""验证配置有效性"""
|
||||
required_fields = ['protocol', 'ssl', 'email_url', 'executornum', 'pyno_user_token']
|
||||
for field in required_fields:
|
||||
if field not in self.config:
|
||||
raise ValueError(f"配置缺少必要字段: {field}")
|
||||
|
||||
def _load_config(self, config_path):
|
||||
"""加载配置"""
|
||||
with open(config_path, 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
def parse_email_credentials(self, line):
|
||||
"""解析邮件凭据"""
|
||||
parts = line.strip().split("----")
|
||||
if len(parts) == 2:
|
||||
return {
|
||||
'email': parts[0],
|
||||
'password': parts[1]
|
||||
}
|
||||
elif len(parts) == 4:
|
||||
return {
|
||||
'email': parts[0],
|
||||
'password': parts[1],
|
||||
'client_id': parts[2],
|
||||
'refresh_token': parts[3]
|
||||
}
|
||||
raise ValueError("Invalid email credentials format")
|
||||
|
||||
def _get_registration(self):
|
||||
"""获取线程本地的SteamRegistrationWithPyno实例"""
|
||||
if not hasattr(self._registration_local, 'registration'):
|
||||
registration = SteamRegistrationWithPyno(
|
||||
self.config,
|
||||
self.proxy_pool,
|
||||
)
|
||||
self._registration_local.registration = registration
|
||||
# 将新创建的实例添加到跟踪集合
|
||||
with self._registrations_lock:
|
||||
self._registrations.add(registration)
|
||||
return self._registration_local.registration
|
||||
|
||||
def process_email(self, email_data):
|
||||
registration = self._get_registration()
|
||||
registration.main(email_data)
|
||||
|
||||
|
||||
def stop(self):
|
||||
"""停止所有任务"""
|
||||
self._running = False
|
||||
# 首先关闭线程池,不再接受新任务
|
||||
self.executor.shutdown(wait=False)
|
||||
|
||||
# 遍历并停止所有注册实例
|
||||
with self._registrations_lock:
|
||||
for registration in self._registrations:
|
||||
try:
|
||||
registration.running = False
|
||||
if (hasattr(registration, 'session') and
|
||||
registration.session and
|
||||
not getattr(registration.session, 'closed', True)):
|
||||
# 只有当session存在且未关闭时才进行关闭
|
||||
registration.session.close()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
# 清空实例集合
|
||||
self._registrations.clear()
|
||||
|
||||
def start(self):
|
||||
"""启动处理"""
|
||||
self._running = True
|
||||
try:
|
||||
with open(self.email_file, "r") as file:
|
||||
for line in file:
|
||||
if not self._running:
|
||||
break
|
||||
try:
|
||||
email_data = self.parse_email_credentials(line.strip())
|
||||
self.executor.submit(self.process_email, email_data)
|
||||
except ValueError as e:
|
||||
print(f"错误的邮箱格式: {e}")
|
||||
continue
|
||||
finally:
|
||||
self.executor.shutdown(wait=True)
|
||||
|
||||
class GUIThreadManagerWithPyno(ThreadManagerWithPyno):
|
||||
def __init__(self, config_path, email_file_path, proxy_file_path, gui, completed_tasks=None):
|
||||
super().__init__(config_path, email_file_path, proxy_file_path)
|
||||
self.gui = gui
|
||||
self.completed_tasks = completed_tasks or set()
|
||||
|
||||
def process_email(self, email_data):
|
||||
"""处理单个邮件账号"""
|
||||
try:
|
||||
if not self._running: # 检查是否应该继续
|
||||
self.gui.update_status(email_data['email'], "任务已停止")
|
||||
return
|
||||
|
||||
# 先更新状态为"准备中"
|
||||
self.gui.update_status(email_data['email'], "准备验证邮箱...")
|
||||
|
||||
# 获取注册实例
|
||||
registration = self._get_registration()
|
||||
registration.set_gui(self.gui) # 设置GUI引用
|
||||
registration.running = self._running
|
||||
|
||||
# 开始处理
|
||||
self.gui.update_status(email_data['email'], "开始验证邮箱")
|
||||
registration.main(email_data)
|
||||
|
||||
except Exception as e:
|
||||
# 捕获所有异常并更新状态
|
||||
error_msg = str(e)
|
||||
# 确保错误信息不包含敏感数据
|
||||
if len(error_msg) > 100:
|
||||
error_msg = error_msg[:100] + "..."
|
||||
self.gui.update_status(email_data['email'], f"处理失败: {error_msg}", result="失败")
|
||||
|
||||
def start(self):
|
||||
"""启动处理"""
|
||||
self._running = True
|
||||
with open(self.email_file, 'r', encoding='utf-8') as file:
|
||||
with ThreadPoolExecutor(max_workers=self.config['executornum']) as self.executor:
|
||||
for line in file:
|
||||
if not self._running:
|
||||
break
|
||||
try:
|
||||
email_data = self.parse_email_credentials(line)
|
||||
# 跳过已完成的任务
|
||||
if email_data['email'] not in self.completed_tasks:
|
||||
self.executor.submit(self.process_email, email_data)
|
||||
except ValueError as e:
|
||||
self.gui.update_status(email_data['email'],f"解析邮箱文件失败: {e}")
|
||||
BIN
__pycache__/ProxyPool.cpython-312.pyc
Normal file
BIN
__pycache__/ProxyPool.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/PynoCaptchaSolver.cpython-312.pyc
Normal file
BIN
__pycache__/PynoCaptchaSolver.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/RegistrationGUIWithPynoV2.cpython-312.pyc
Normal file
BIN
__pycache__/RegistrationGUIWithPynoV2.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/SteamCaptchaHelper.cpython-312.pyc
Normal file
BIN
__pycache__/SteamCaptchaHelper.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/SteamRegistrationWithPyno.cpython-312.pyc
Normal file
BIN
__pycache__/SteamRegistrationWithPyno.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/ThreadManagerWithPyno.cpython-312.pyc
Normal file
BIN
__pycache__/ThreadManagerWithPyno.cpython-312.pyc
Normal file
Binary file not shown.
1
accounts_succ.txt
Normal file
1
accounts_succ.txt
Normal file
@@ -0,0 +1 @@
|
||||
ejd71m5tr----z1xG24ZXbHp----5ulxb79e@evnmail.com----dr!mueh15ahG
|
||||
12
config.json
Normal file
12
config.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"protocol": "IMAP",
|
||||
"ssl": true,
|
||||
"email_url": "mail.evnmail.com",
|
||||
"executornum": 1,
|
||||
"pyno_user_token": "cf169d36-0d62-45da-bff7-1eff42bbc4f3",
|
||||
"pyno_sitekey": "eb9cbe72-814a-4392-b9b2-f8965f3686ee",
|
||||
"pyno_referer": "https://store.steampowered.com/join/",
|
||||
"pyno_user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36",
|
||||
"pyno_timeout": 60,
|
||||
"pyno_debug": true
|
||||
}
|
||||
1
email_password.txt
Normal file
1
email_password.txt
Normal file
@@ -0,0 +1 @@
|
||||
5ulxb79e@evnmail.com----dr!mueh15ahG
|
||||
1
proxy_ips.txt
Normal file
1
proxy_ips.txt
Normal file
@@ -0,0 +1 @@
|
||||
gw.dataimpulse.com:823:3b9936d2ce39b35c4bdf:2263006e0ff05530
|
||||
1
rgerror.txt
Normal file
1
rgerror.txt
Normal file
@@ -0,0 +1 @@
|
||||
5ulxb79e@evnmail.com----dr!mueh15ahG
|
||||
17
start_pyno_v3.py
Normal file
17
start_pyno_v3.py
Normal file
@@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Steam注册程序 - PyNoCaptcha V3版本启动器
|
||||
使用PyNoCaptcha解决验证码,解决了sitekey获取问题
|
||||
"""
|
||||
|
||||
import tkinter as tk
|
||||
from RegistrationGUIWithPynoV2 import RegistrationGUIWithPynoV2
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("正在启动Steam注册助手 PyNoCaptcha V3版本...")
|
||||
print("这个版本修复了验证码头信息问题,使用正确的User-Agent获取sitekey")
|
||||
root = tk.Tk()
|
||||
gui = RegistrationGUIWithPynoV2(root)
|
||||
root.mainloop()
|
||||
179
steam_registration_pyno.log
Normal file
179
steam_registration_pyno.log
Normal file
@@ -0,0 +1,179 @@
|
||||
2025-05-22 18:05:35.258 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:05:35.916 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 17593453638535276028
|
||||
2025-05-22 18:05:35.917 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 18:05:36.296 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986341176
|
||||
2025-05-22 18:05:36.299 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:05:36.325 | DEBUG | PynoCaptchaSolver:__init__:21 - PynoCaptchaSolver 初始化 - 使用 PyNoCaptcha 库
|
||||
2025-05-22 18:05:36.341 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:31 - 开始解决验证码 - sitekey: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:05:36.343 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:32 - 使用User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36
|
||||
2025-05-22 18:05:36.346 | DEBUG | pynocaptcha.crackers.base:__init__:58 - 感谢选择 nocaptcha, 我们只做别人做不到的(手动狗头)~
|
||||
2025-05-22 18:05:36.347 | DEBUG | pynocaptcha.crackers.base:__init__:59 - 欢迎推荐注册, 官网地址: https://www.nocaptcha.io/
|
||||
2025-05-22 18:05:36.348 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:45 - 调用 PyNoCaptcha 进行破解
|
||||
2025-05-22 18:05:43.925 | INFO | pynocaptcha.crackers.base:crack:153 - {'status': 1, 'msg': '验证成功', 'id': 'cfffdb69-6885-49be-a5f5-e16d5286fbe9', 'cost': '6834.29ms', 'data': {'generated_pass_UUID': 'P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQOltp3ltqiset16UHk24wluUI5MNqjTWl-pg6bi80iT3MO-LpDJyN4rmCDjo7XFO7wlE3mr3HTmp3H7BNvBg4XgpORGD7Jd6Bua7y_TfT2qNFNp-l2zH98ywODwZaGp-BvvdgplW7UQvgtn95vvYDrrVBQHI6a9W6pFP1rKj0KZj2vxATmuNbVBg5qAywUJF57-HfuqUIAFmXA4oPnpnHbBWwefkpLFnZCf2ZQ_bZBC2Xn91SFVSUSS8aMW0g68u5lqYawAxUeIibhaL6ZqIPTx9jFKkQqBQvF4x0NDK_HERoVkwuxZRw3aKc6msbB-Ibrbyu9IhiyAT_I08LADsj9VOtQnJge1cRJ9MhEwsxWmZy-Zcxg9q6B9W7Gqg2af8CxyyT4Uc-tLzev9wmr27D1_ugGL0rUEgj6r3x7EZtdqjwjKRwaprrM2w89iNanUWTaAWiVCXc1dDa0YpOwrNfqMbdM6WFQXOsohqwQP48ippYAa7ARWkD2sI4IwmR9W8u3Njj1qKhQ9uV3fK_05cI4sojvWKKiNuajTXgtvBUuh7Ev4-342tR0mbfzJ4cn2XekmrNHw_42lJ7pCWh0ZJSi-Iz8xsQ_brxUSE0lEuLvxRhWspgYd0afUMicd2EY38GBy-NEgmRONGQS0eK9rnuY_-jCuYm8RY6m490I7KfzpifnfCylq-VGeQ1qtrgW5CVXZYtuoCjmxKMCgMSbjPipvfrUFsaza6JLrbeeVZLqlFsZbUWXhpfXykEPM3fsgXWlMH4OA7yTrPEW6h5ym8FB0s8ihY5nWnc7yT56KIYCf991EBXm7FpNP3ijYGae9yFys8lgcx30T27e-OBt8amIXhJNo80iytijDD_QWh4PbhsRh7Ztw08JjBfKvGAUP5sebu8zI5YK7udTSmJFv9ee1CyxbjXx90j4VVJMOSjkdUbo9JJfodE6_r7ve2J-t9hSWs_ylWbSaB1bF59q7hrlI_S4vKWNtd2CQpKsIBSkk5lm4HVpe6XNi6ncS7z5LOZGFqMcuEQTEd0krjp84F1Gi7tq9SOIxGuAgtZC2p1s8pW9p34xY979-40zUxJPsqasHNtpcwNtszwKwwUO4mOMoRtji9ZnTe_fnefvcTudDHlr82XsGVmGvYrsWvPB1P_OUCSj212IGu_FJGP9-8B5cGvsIgmNlwd2Drolrw-feaduS8RG03EfPWHccCg3wJ_5xjIhVFrqgaPZCu-FfKXCABJXgWi7io2V4cM5oLvdvqHNoYXJkX2lkzg9y6m-ia3KoMWNmODU4ODKicGQA.0PCJXfyqO4HUbOQWBOjYW9JP2mBPzHH5OS2FnR4lBTw', 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1745876290) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36'}, 'extra': {}, 'en_msg': 'Verify success'}
|
||||
2025-05-22 18:05:43.927 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:49 - 验证码破解成功
|
||||
2025-05-22 18:05:43.961 | INFO | SteamCaptchaHelper:verify_email:72 - 验证邮箱: 749army@gmail.com
|
||||
2025-05-22 18:05:44.411 | INFO | SteamCaptchaHelper:verify_email:87 - 验证邮箱结果: {'success': 1, 'sessionid': '3145536910878670205', 'details': ''}
|
||||
2025-05-22 18:05:59.312 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:05:59.661 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 232517025202945862
|
||||
2025-05-22 18:05:59.662 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 18:05:59.975 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986341532
|
||||
2025-05-22 18:05:59.977 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:06:01.071 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:01.597 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:03.644 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:04.129 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:06.206 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:06.670 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:08.719 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:09.190 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:11.276 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:11.743 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:13.787 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:14.265 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:16.317 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:16.794 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:18.841 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:19.305 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:22.443 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:22.926 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:28.298 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:28.789 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:34.104 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:34.579 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:39.936 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:40.392 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:45.655 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:46.269 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:51.679 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:52.140 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:06:57.405 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:06:57.880 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:03.151 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:03.645 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:08.911 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:09.372 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:14.648 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:15.114 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:20.404 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:20.865 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:26.140 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:26.608 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:31.877 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:32.377 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:37.651 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:38.116 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:43.399 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:43.936 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:49.217 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:49.730 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:07:54.997 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:07:55.523 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:00.784 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:01.378 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:06.645 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:06.950 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:12.235 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:12.590 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:12.710 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:13.450 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 17683348673253827567
|
||||
2025-05-22 18:08:13.452 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 18:08:13.765 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986343432
|
||||
2025-05-22 18:08:13.766 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:08:14.817 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:15.275 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:17.310 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:17.780 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:17.982 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:18.459 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:19.817 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:20.286 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:22.324 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:22.811 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:23.838 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:24.296 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:24.850 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:25.326 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:27.369 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:27.843 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:29.888 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:30.366 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:32.398 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:32.702 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:34.734 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:35.205 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:37.245 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:37.710 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:39.743 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:40.223 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:42.267 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:42.579 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:44.615 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:45.075 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:47.120 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:47.427 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:49.463 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:49.942 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:51.986 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:52.457 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:54.497 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:54.962 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:56.990 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:57.299 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:08:59.349 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:08:59.838 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:09:01.899 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:09:02.475 | ERROR | SteamCaptchaHelper:get_sitekey:66 - 获取sitekey过程中出错: HTTPSConnectionPool(host='store.steampowered.com', port=443): Max retries exceeded with url: /join/ (Caused by ProxyError('Cannot connect to proxy.', OSError('Tunnel connection failed: 403 Forbidden')))
|
||||
2025-05-22 18:28:03.451 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:28:04.042 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 12411724988176453952
|
||||
2025-05-22 18:28:04.045 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 18:28:04.374 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986360263
|
||||
2025-05-22 18:28:04.375 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:28:05.423 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 18:28:08.085 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 9685715838321349259
|
||||
2025-05-22 18:28:08.087 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 18:28:08.785 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 5178056896388019
|
||||
2025-05-22 18:28:08.787 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:28:08.804 | DEBUG | PynoCaptchaSolver:__init__:21 - PynoCaptchaSolver 初始化 - 使用 PyNoCaptcha 库
|
||||
2025-05-22 18:28:08.806 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:31 - 开始解决验证码 - sitekey: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 18:28:08.807 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:32 - 使用User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36
|
||||
2025-05-22 18:28:08.808 | DEBUG | pynocaptcha.crackers.base:__init__:58 - 感谢选择 nocaptcha, 我们只做别人做不到的(手动狗头)~
|
||||
2025-05-22 18:28:08.809 | DEBUG | pynocaptcha.crackers.base:__init__:59 - 欢迎推荐注册, 官网地址: https://www.nocaptcha.io/
|
||||
2025-05-22 18:28:08.810 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:45 - 调用 PyNoCaptcha 进行破解
|
||||
2025-05-22 18:28:15.693 | INFO | pynocaptcha.crackers.base:crack:153 - {'status': 1, 'msg': '验证成功', 'id': '6c04790c-1097-410b-adf1-a5d2240a000f', 'cost': '6150.71ms', 'data': {'generated_pass_UUID': 'P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQOlK8mkTImlsBoatBxSNYDqDmJIB7oihj5M9YTIa0epQU7HVi4rr027uynB6YXihE-n4k0gt-GUcxs9viLCZeaLVycviwe4h9QHgjeubbIDIvfeNMp_bbU1xOXuxrL1UN_6OSktEFgfPEaambWm4v7s6jCjv0TwXFepzS4CmlBmMf1T3xB_nNburK51zkiRVV1d_UTyvx4gEoSlLapJJ5vZM-k8F1NvWZG0vA_K4m4XsLSt8Vz2Uy5TLPp8mpM3imHAm3zVY2Bk5rsKyNhDUs71S3ct3OrQFhly8P2motuPecviMQOqxXRqCAki8icYn70LBAQM2yQ6UYwgu5pd5UWKrheFX995N0k_RzarWIs-ShddEwzzy6T62lZUjWvJqa16sQSpjQU8w1FJ2MDcz6L54Zct_09uYCEvwwkOfjRc2LAJNv_QaOHokO3coWNW1W7-zSro40bAcbKGxC3z0WQJhbdb5rrO5a1wlIyGi62AQceoCkMuMWtFuuarUQjPHWaLc5ux8z5pzmUXr-k487rMmRsx7TbF6mD5w2bCopa_-aYCKktUgE3teWMmDNHN7c3-n5B_t0kPX5XP9_eNoSK6Ud1CvX7aYwtFyX0oerLc9r_yNMRVJHkg8KXuPxWs9fJCEQO4ARAcsTE9hLhgdPXsR6X2RVBHmn2q62amK1bFmGIkRuSYTUtOhQWHKsIyHKa6YAElDf5vhjHuoU2UzUC5QZPijesdIpHZdt24S_AU4Nwi8RIY3VDAakKR0hpcftmc5-4DKkgLx91V5oj-Hzef5AD8vVAcEsTgjDT33gsez30aDz-qXpuzk2nHqo9BgIBVy63l7lkXhUa3v-q83jqmw4NTBG3ckpRv4KeKioiYJDKm7WPrjkQ4bdXXc36eDXvafT84DuEC1B82SyxqjVydYxySxjjncbW26tRsdltIffv5TCpAJ5gJI0KHLRE4xfYAAWcCpxDU6ZIA52zX6JdyhskCb9smBWGC0eFKAGxAM6i2-atjvGknnkSU-L6kwM7DpvxgtO-iDl7GMC2xfLAvzGbQmGzTTSGtXbDIXRQjF-xw3yieKMOLbpD5KYSjtAiH_2D0qouAMCdtTQXIhup7acrAnlB5Q4HYEiqCjIJGg_lXkcMCKvIMUWlveZUCKMtfkw0PyBveWOSSvkPbD694rrykXYkzl0IObB1SMEWNrrl5mFE7RDhqWhFF7JSj_ELUWXjKL10Jd3ekOqA48FyD7IAGOKfgo2V4cM5oLvy3qHNoYXJkX2lkzg9y6m-ia3KoMjhlOTQ4N2GicGQA.sOwvAIUlF5NO2AMxXECfDVfKi7EKAJtV-HH7uhyQu_I', 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1745876290) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36'}, 'extra': {}, 'en_msg': 'Verify success'}
|
||||
2025-05-22 18:28:15.695 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:49 - 验证码破解成功
|
||||
2025-05-22 20:27:29.115 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 20:27:29.784 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 1862677362228322809
|
||||
2025-05-22 20:27:29.785 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 20:27:30.124 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986473234
|
||||
2025-05-22 20:27:30.125 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:27:31.283 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 20:27:33.570 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 18091961620671672591
|
||||
2025-05-22 20:27:33.572 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 20:27:34.358 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 11933456348020478
|
||||
2025-05-22 20:27:34.360 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:27:34.372 | DEBUG | PynoCaptchaSolver:__init__:21 - PynoCaptchaSolver 初始化 - 使用 PyNoCaptcha 库
|
||||
2025-05-22 20:27:34.374 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:31 - 开始解决验证码 - sitekey: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:27:34.375 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:32 - 使用User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36
|
||||
2025-05-22 20:27:34.376 | DEBUG | pynocaptcha.crackers.base:__init__:58 - 感谢选择 nocaptcha, 我们只做别人做不到的(手动狗头)~
|
||||
2025-05-22 20:27:34.376 | DEBUG | pynocaptcha.crackers.base:__init__:59 - 欢迎推荐注册, 官网地址: https://www.nocaptcha.io/
|
||||
2025-05-22 20:27:34.377 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:45 - 调用 PyNoCaptcha 进行破解
|
||||
2025-05-22 20:27:42.545 | INFO | pynocaptcha.crackers.base:crack:153 - {'status': 1, 'msg': '验证成功', 'id': '68d5df40-ef27-4d3c-b202-9b549d5597c8', 'cost': '7378.42ms', 'data': {'generated_pass_UUID': 'P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQOg7-sqzaJIrXnmUqggD_D9N_zjuUd7g9V4cSaQJn2yNLx1jcL0IQw1CIQsuxv8j3zLtxeRqH_B0piqcJoR3QrgQfTIIaNPi8aE2l4TXyQsVZRqBf9aouKMBdbZ5cdSM7MBLCPh7ZWXImfu34xRkONTXrx_9wpm6m2TfIyXkHBlmQCCF-iHjkJAKQtdghuXfSZTXBzc2IG2bdFZFRemfJTgPZpdPvjP3RaD-TjwbIdRU1yrDxQDrUO2W7Saax8qc7huwfGIVl__iTYS7ZPL8PuHBNXX2NGLbuVJw2oltOcr0rP6y2Fb2JaU6mewyuixeGRMGL2zDiC0OjSzg6KSwdr5-7L8ueiPnA_NT8oIF_PoFi4O9IOatx6gCxNevgJjM4a9zBOOchjXgXIRZ3CbmLckAPzU9njcsoM5SIg1lrMXPASk4aoI2D0xgNZ5-2crAHW9Hn8u8sIukWWH3bcoQdNZ2XFvITbXf5YjyHVHQDvcym4r-VMffmsqD4qWEfZT5_kGITbpHLjC3Zk9_UuDLaPyEyqkIvmyhlfTY77P4EcILLlnV6QGZ7Jp6NpXvbw1hiK-CLSLluYf7iN1PK079TUkTsHVBkUG3LakJBAQfY1FIgb6zScPvd51oyc5HIAjVXf_0DDaQSl71IaP6vPAGdez0Tl2bSzmio8y0YZv-nmGTVL5hpVPlDz--UAeyAoYF2b986xpySCPn9fOm_ftCVST6yVbYRPrv6UAC-ya0y1RwXtsKP5iB8ZsYT5t2vn1K8MypVCwCwhK7bZsBqBTawkcSKgOmKt-Bk_uYAt6gJJeuPM_jwGoiMqLIqfH61qavl49NicpbS3XmuA10xTnhf-5hsV5yT1GYvWAN7pAfyftpoLZU6w3KWwV3bZpkd7Y_6KMkbHXDs-dPXUQyD2TmMS-o-TCiXJSJTgPQ3O-GWCCnmJa62RYSkd07FoWTO4t1-2qHuzMntwEwElvCl5sNcybLymA71iFyxia22Kj0MbdMXSa6ZfE7BQTfgNzRLlClrT8myvFodN4fqJ7l6IiBLMZLAF2LmSWRFoqlZfJsSd5UM_nhhbNqAt-n7EyZ9naPU0JFcd5HrdodIAMJzz_EM5cNRkIJLID4TyHjG591l9JP6WBy0MRHz4bGYa_R2b7DHVG__-H0H-JyPX5txSa0gA4zGPhmUq0MyPc4O46iMbCPVW1ZGJq_52XBTmDsIu7CabmfBa4jsz4uugzfGP8AWuFrqNleHDOaC8YtqhzaGFyZF9pZM4xrUyBomtyqDE2ZDQ1YTU3onBkAA.tfSoMC6piw9EwluZobqrWQgblQupX6ruwU3Y2HZnA48', 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1745876290) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36'}, 'extra': {}, 'en_msg': 'Verify success'}
|
||||
2025-05-22 20:27:42.548 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:49 - 验证码破解成功
|
||||
2025-05-22 20:32:30.378 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 20:32:31.108 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 1027762256794772261
|
||||
2025-05-22 20:32:31.109 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 20:32:31.466 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 4052156986478325
|
||||
2025-05-22 20:32:31.467 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:32:32.540 | INFO | SteamCaptchaHelper:get_sitekey:32 - 获取Steam注册页面...
|
||||
2025-05-22 20:32:34.746 | INFO | SteamCaptchaHelper:get_sitekey:41 - 获取init_id成功: 8413603079758422192
|
||||
2025-05-22 20:32:34.748 | INFO | SteamCaptchaHelper:get_sitekey:47 - 刷新验证码获取sitekey...
|
||||
2025-05-22 20:32:35.412 | INFO | SteamCaptchaHelper:get_sitekey:56 - 获取gid成功: 9681656522876689
|
||||
2025-05-22 20:32:35.414 | INFO | SteamCaptchaHelper:get_sitekey:57 - 获取sitekey成功: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:32:35.434 | DEBUG | PynoCaptchaSolver:__init__:21 - PynoCaptchaSolver 初始化 - 使用 PyNoCaptcha 库
|
||||
2025-05-22 20:32:35.435 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:31 - 开始解决验证码 - sitekey: eb9cbe72-814a-4392-b9b2-f8965f3686ee
|
||||
2025-05-22 20:32:35.436 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:32 - 使用User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1741737356) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36
|
||||
2025-05-22 20:32:35.437 | DEBUG | pynocaptcha.crackers.base:__init__:58 - 感谢选择 nocaptcha, 我们只做别人做不到的(手动狗头)~
|
||||
2025-05-22 20:32:35.439 | DEBUG | pynocaptcha.crackers.base:__init__:59 - 欢迎推荐注册, 官网地址: https://www.nocaptcha.io/
|
||||
2025-05-22 20:32:35.440 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:45 - 调用 PyNoCaptcha 进行破解
|
||||
2025-05-22 20:32:46.830 | INFO | pynocaptcha.crackers.base:crack:153 - {'status': 1, 'msg': '验证成功', 'id': 'a7132448-c13d-47c2-a43d-45f25fa55fe3', 'cost': '10724.15ms', 'data': {'generated_pass_UUID': 'P1_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.hadwYXNza2V5xQPLkrRxA4I1L_dNjMveRwgNdFIJwws0gH5K_LcfPtEL_A6eSMvcaXZWDAVmkYKjhuP_-OYLyAPW_JkOIXbINjnsHyhRP7XBQn65fzBQPnZnNZuh-shaKwLiUWGvuU4gUukbOUnzcVUM5p2GDaouW1Y_37-ZuNS_XJ5IfF6CHXT8aQUpMhDkeaKGgsYO3YMfUQDqnDHzyVEJoHLkENLF1F4nDwlPjufw4a-Wh1XHdObypfSRcYk4HXlSLqohxEcFV0y6dJopdbeTi-v6RTBqbykfOOAjht8qa85nZQNwfhPGF_8m6zc5yrLMTvU-_7av6tBbaxfGAvP-kOvjGbRnLJ2FEOePlvLcJ8K3YOadDaIFvqcljXZi98lnX1Qafz4pzZOdXoSBiI5dmsOQF9VJwlDKQ3uv8kRh2BD_53J2czirycIdFV021rkAIWJAxPX6ROVKDpgM2kh-kuMmpvutSfmaSn-P7rbWNVD57Rd4z3Q8HJ3KDPhTbt6NC4sSULHvpi49zcnbNsqOs-5RykiyLgnbgk8n8rfF8Z7aytxj4V5hCUEi8ci8GiUNXxc1SKyNbw4hT1bEa5wVxv0Ju67JYV-Eu5HrnRyZMUNpEkB-S90xYBOstwNEV7ik8jI_G_QXbLTEv7R8Rs_aMBVmmys0zfz0Ei5uCuPf66EQkVkUqEorK7-e26SYF6Zsf9VS4hCySpdxrbLg7nOs1NIqz2D2O9MC_kJmK2PgYSQyA1YW3hnE6TTPEyJxP1BTYPRs5R882TrfryETz_U1XEEAslAhvqjK10SFIIpJBiJNbytsKQpHpaQ3nER0XSKw-jVJ1x27g_IOpSmmXzZQHWz7NZcNflBAe4Pa7oxxxdxoc5RcR8sKTMtyxMOP4aS1ztOlTojx8BzDrnCnKQYRJYyzA4jH54Q0Bm_179j6EN8m26MjxwSpYO3hAtpnnmU5Qj1dmQ6gKAOEB8izxS4ZwH1UcRYIAjHjw4Oqo7S__-DZe5mL7tkg5UVB6weZxxTSBjRrI9rEuzJNN2woULcL1mRGrk23EKtSpxnGqKVgwuORHSBhTs1boOnyQbMtV9Z_EWZ_Dom0QhT73SvuP3WfA_fJhn7VPOsVFOeed6iQcF5apaZJmn1W3c-9KRVxx4FmIlliObdN1wCjD2gXIBM2_AasYdx3XxOtX1hS41zCIR1zWs61kN7eIEXHWRjLwEmIgsYi_6Qtob5-SD--47aY3dsPWp8iUv90eT6MCV0hi2FgNXeotSXPmDo3uJHQU4wZ6S6eFaNSUZegFj-7rKk6y1bzFqOjZXhwzmgvGeaoc2hhcmRfaWTOD3Lqb6JrcqgzNDVlOWNmN6JwZAA.KQolAEKV9I6DIOmDhavMZkJjOSw0tv5xji-3HY20vYQ', 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; Valve Steam Client/default/1745876290) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.6478.183 Safari/537.36'}, 'extra': {}, 'en_msg': 'Verify success'}
|
||||
2025-05-22 20:32:46.833 | DEBUG | PynoCaptchaSolver:solve_hcaptcha:49 - 验证码破解成功
|
||||
203
test_imap.py
Normal file
203
test_imap.py
Normal file
@@ -0,0 +1,203 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
测试IMAP邮件获取功能
|
||||
单独测试邮箱取件功能
|
||||
"""
|
||||
|
||||
import imaplib
|
||||
import email
|
||||
import email.header
|
||||
import sys
|
||||
from email.parser import BytesParser
|
||||
from email.policy import default
|
||||
import re
|
||||
import time
|
||||
from urllib.parse import urlparse, parse_qs
|
||||
|
||||
# 邮箱配置
|
||||
EMAIL_ADDRESS = "5ulxb79e@evnmail.com"
|
||||
EMAIL_PASSWORD = "dr!mueh15ahG"
|
||||
IMAP_SERVER = "mail.evnmail.com"
|
||||
USE_SSL = True
|
||||
|
||||
def decode_mime_words(text):
|
||||
"""解码MIME编码的文本"""
|
||||
if not text:
|
||||
return ""
|
||||
try:
|
||||
decoded = email.header.decode_header(text)
|
||||
return " ".join([
|
||||
(str(t[0], t[1] or 'utf-8') if isinstance(t[0], bytes) else str(t[0]))
|
||||
for t in decoded
|
||||
])
|
||||
except:
|
||||
return text
|
||||
|
||||
def get_body_text(msg):
|
||||
"""获取邮件正文文本内容"""
|
||||
if msg.is_multipart():
|
||||
# 如果邮件包含多个部分,递归处理
|
||||
text_parts = []
|
||||
for part in msg.get_payload():
|
||||
if part.get_content_type() == 'text/plain':
|
||||
charset = part.get_content_charset() or 'utf-8'
|
||||
try:
|
||||
text_parts.append(part.get_payload(decode=True).decode(charset))
|
||||
except:
|
||||
text_parts.append("[无法解码的内容]")
|
||||
elif part.is_multipart():
|
||||
# 递归处理多部分
|
||||
text_parts.append(get_body_text(part))
|
||||
return "\n".join(text_parts)
|
||||
else:
|
||||
# 单部分邮件
|
||||
content_type = msg.get_content_type()
|
||||
if content_type == 'text/plain':
|
||||
charset = msg.get_content_charset() or 'utf-8'
|
||||
try:
|
||||
return msg.get_payload(decode=True).decode(charset)
|
||||
except:
|
||||
return "[无法解码的内容]"
|
||||
else:
|
||||
return f"[内容类型: {content_type}]"
|
||||
|
||||
def extract_urls_from_body(body, pattern):
|
||||
"""从邮件正文中提取URL"""
|
||||
found_urls = re.findall(pattern, body)
|
||||
return [url.replace('&', '&').replace("=3D", "=").replace("=\r\n", "")
|
||||
.replace("\r\n", "").replace("=\n", "").replace("\n", "")
|
||||
for url in found_urls]
|
||||
|
||||
def test_imap_connection():
|
||||
"""测试IMAP连接"""
|
||||
print(f"正在测试连接到 {IMAP_SERVER}...")
|
||||
try:
|
||||
# 连接到IMAP服务器
|
||||
if USE_SSL:
|
||||
mail = imaplib.IMAP4_SSL(IMAP_SERVER)
|
||||
else:
|
||||
mail = imaplib.IMAP4(IMAP_SERVER)
|
||||
|
||||
# 登录
|
||||
print(f"正在登录邮箱 {EMAIL_ADDRESS}...")
|
||||
mail.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
|
||||
print("登录成功!")
|
||||
|
||||
# 关闭连接
|
||||
mail.logout()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"连接失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def fetch_emails():
|
||||
"""获取邮件"""
|
||||
urls = []
|
||||
try:
|
||||
# 连接到IMAP服务器
|
||||
if USE_SSL:
|
||||
mail = imaplib.IMAP4_SSL(IMAP_SERVER)
|
||||
else:
|
||||
mail = imaplib.IMAP4(IMAP_SERVER)
|
||||
|
||||
# 登录
|
||||
print(f"正在登录邮箱 {EMAIL_ADDRESS}...")
|
||||
mail.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
|
||||
print("登录成功!")
|
||||
|
||||
# 只检查INBOX文件夹
|
||||
steam_verification_pattern = r'https://store\.steampowered\.com/account/newaccountverification\?[^\s"\'<>]+'
|
||||
|
||||
try:
|
||||
print("\n检查文件夹: INBOX")
|
||||
mail.select("INBOX")
|
||||
status, messages = mail.search(None, "ALL")
|
||||
if status != "OK" or not messages[0]:
|
||||
print(" INBOX为空或无法访问")
|
||||
else:
|
||||
# 获取邮件ID列表,从最新的开始
|
||||
message_ids = messages[0].split()
|
||||
message_count = len(message_ids)
|
||||
print(f" 找到 {message_count} 封邮件")
|
||||
|
||||
# 最多检查10封最新邮件
|
||||
check_count = min(10, message_count)
|
||||
message_ids = message_ids[-check_count:]
|
||||
message_ids.reverse() # 最新的邮件放在前面
|
||||
|
||||
for i, msg_id in enumerate(message_ids):
|
||||
print(f"\n 正在检查邮件 {i+1}/{check_count}, ID: {msg_id.decode()}...")
|
||||
status, msg_data = mail.fetch(msg_id, "(RFC822)")
|
||||
if status != "OK":
|
||||
print(" 无法获取邮件内容")
|
||||
continue
|
||||
|
||||
# 解析邮件内容
|
||||
raw_email = msg_data[0][1]
|
||||
msg = email.message_from_bytes(raw_email, policy=default)
|
||||
|
||||
# 提取信息
|
||||
subject = decode_mime_words(msg["Subject"])
|
||||
from_addr = decode_mime_words(msg["From"])
|
||||
date = decode_mime_words(msg["Date"])
|
||||
|
||||
print(f" 主题: {subject}")
|
||||
print(f" 发件人: {from_addr}")
|
||||
print(f" 日期: {date}")
|
||||
|
||||
# 获取正文
|
||||
body = get_body_text(msg)
|
||||
body_preview = body[:100] + "..." if len(body) > 100 else body
|
||||
print(f" 正文预览: {body_preview}")
|
||||
|
||||
# 查找Steam验证链接
|
||||
found_urls = extract_urls_from_body(body, steam_verification_pattern)
|
||||
if found_urls:
|
||||
print(f" 发现 {len(found_urls)} 个可能的Steam验证链接:")
|
||||
for url in found_urls:
|
||||
print(f" {url[:80]}...")
|
||||
urls.append(url)
|
||||
else:
|
||||
print(" 未发现Steam验证链接")
|
||||
except Exception as e:
|
||||
print(f"处理INBOX出错: {str(e)}")
|
||||
|
||||
# 尝试关闭连接
|
||||
try:
|
||||
mail.close()
|
||||
except:
|
||||
pass
|
||||
mail.logout()
|
||||
|
||||
except Exception as e:
|
||||
print(f"IMAP连接错误: {str(e)}")
|
||||
|
||||
return urls
|
||||
|
||||
def main():
|
||||
print("=" * 60)
|
||||
print("IMAP邮件获取测试")
|
||||
print("=" * 60)
|
||||
|
||||
# 测试连接
|
||||
if not test_imap_connection():
|
||||
print("IMAP连接测试失败,程序退出")
|
||||
return 1
|
||||
|
||||
print("\n开始获取邮件...")
|
||||
urls = fetch_emails()
|
||||
|
||||
if urls:
|
||||
print("\n" + "=" * 60)
|
||||
print(f"共找到 {len(urls)} 个可能的Steam验证链接:")
|
||||
for i, url in enumerate(urls):
|
||||
print(f"{i+1}. {url}")
|
||||
else:
|
||||
print("\n没有找到任何Steam验证链接")
|
||||
|
||||
return 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
5
启动Steam注册.bat
Normal file
5
启动Steam注册.bat
Normal file
@@ -0,0 +1,5 @@
|
||||
@echo off
|
||||
echo 正在启动Steam注册 V3版本...
|
||||
echo 这个版本修复了验证码头信息问题,确保使用正确的User-Agent
|
||||
python start_pyno_v3.py
|
||||
pause
|
||||
Reference in New Issue
Block a user