Rewrite as Windows Wi-Fi monitor service
This commit is contained in:
247
main.py
247
main.py
@@ -1,248 +1,5 @@
|
||||
import argparse
|
||||
import random
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
import requests
|
||||
import winreg
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.edge.options import Options
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
# Captive Portal 触发 URL 列表,按优先级依次尝试
|
||||
CAPTIVE_PORTAL_URLS = [
|
||||
"http://captive.apple.com/",
|
||||
"http://www.msftconnecttest.com/redirect",
|
||||
"http://detectportal.firefox.com/",
|
||||
]
|
||||
|
||||
MAX_LOGIN_RETRIES = 3
|
||||
|
||||
|
||||
def is_connected():
|
||||
"""通过 HTTP 204 检测网络是否连通。"""
|
||||
test_urls = [
|
||||
("http://clients3.google.com/generate_204", 204),
|
||||
("http://www.msftconnecttest.com/connecttest.txt", 200),
|
||||
]
|
||||
for url, expected_status in test_urls:
|
||||
try:
|
||||
r = requests.get(url, timeout=3)
|
||||
if r.status_code == expected_status:
|
||||
return True
|
||||
except Exception:
|
||||
continue
|
||||
return False
|
||||
|
||||
|
||||
def get_wifi_adapter_name():
|
||||
"""获取当前活跃的 Wi-Fi 网卡名称。"""
|
||||
result = subprocess.run(
|
||||
["netsh", "wlan", "show", "interfaces"],
|
||||
capture_output=True, text=True, encoding="gbk",
|
||||
)
|
||||
for line in result.stdout.splitlines():
|
||||
line = line.strip()
|
||||
if line.startswith("名称") or line.startswith("Name"):
|
||||
return line.split(":", 1)[1].strip()
|
||||
return None
|
||||
|
||||
|
||||
def generate_random_mac():
|
||||
"""生成一个随机的本地管理单播 MAC 地址。"""
|
||||
mac = [random.randint(0x00, 0xFF) for _ in range(6)]
|
||||
mac[0] = (mac[0] & 0xFC) | 0x02 # 本地管理、单播
|
||||
return mac
|
||||
|
||||
|
||||
def find_adapter_registry_key(adapter_name):
|
||||
"""在注册表中找到匹配 adapter_name 的网卡子键路径。"""
|
||||
base_path = r"SYSTEM\CurrentControlSet\Control\Class\{4d36e972-e325-11ce-bfc1-08002be10318}"
|
||||
try:
|
||||
base_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, base_path)
|
||||
except OSError:
|
||||
return None
|
||||
|
||||
index = 0
|
||||
while True:
|
||||
try:
|
||||
subkey_name = winreg.EnumKey(base_key, index)
|
||||
index += 1
|
||||
except OSError:
|
||||
break
|
||||
try:
|
||||
subkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, f"{base_path}\\{subkey_name}")
|
||||
driver_desc, _ = winreg.QueryValueEx(subkey, "DriverDesc")
|
||||
if adapter_name.lower() in driver_desc.lower():
|
||||
winreg.CloseKey(subkey)
|
||||
winreg.CloseKey(base_key)
|
||||
return f"{base_path}\\{subkey_name}"
|
||||
winreg.CloseKey(subkey)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
winreg.CloseKey(base_key)
|
||||
return None
|
||||
|
||||
|
||||
def randomize_mac():
|
||||
"""随机化当前 Wi-Fi 网卡的 MAC 地址(需要管理员权限)。"""
|
||||
adapter_name = get_wifi_adapter_name()
|
||||
if not adapter_name:
|
||||
print("错误:未找到活跃的 Wi-Fi 适配器。")
|
||||
return False
|
||||
|
||||
print(f"找到 Wi-Fi 适配器: {adapter_name}")
|
||||
|
||||
reg_path = find_adapter_registry_key(adapter_name)
|
||||
if not reg_path:
|
||||
print(f"错误:未在注册表中找到适配器 '{adapter_name}' 的条目。")
|
||||
return False
|
||||
|
||||
mac = generate_random_mac()
|
||||
mac_str = "".join(f"{b:02X}" for b in mac)
|
||||
mac_display = ":".join(f"{b:02X}" for b in mac)
|
||||
|
||||
try:
|
||||
key = winreg.OpenKey(
|
||||
winreg.HKEY_LOCAL_MACHINE, reg_path, 0, winreg.KEY_SET_VALUE,
|
||||
)
|
||||
winreg.SetValueEx(key, "NetworkAddress", 0, winreg.REG_SZ, mac_str)
|
||||
winreg.CloseKey(key)
|
||||
except PermissionError:
|
||||
print("错误:需要管理员权限来修改 MAC 地址。请以管理员身份运行。")
|
||||
return False
|
||||
|
||||
print(f"正在将 MAC 地址更改为: {mac_display}")
|
||||
|
||||
# 获取网络适配器的接口名称(用于 netsh)
|
||||
interface_name = get_netsh_interface_name()
|
||||
if not interface_name:
|
||||
interface_name = adapter_name
|
||||
|
||||
print("正在重启网卡以应用新 MAC 地址...")
|
||||
subprocess.run(
|
||||
["netsh", "interface", "set", "interface", interface_name, "disable"],
|
||||
capture_output=True,
|
||||
)
|
||||
time.sleep(2)
|
||||
subprocess.run(
|
||||
["netsh", "interface", "set", "interface", interface_name, "enable"],
|
||||
capture_output=True,
|
||||
)
|
||||
time.sleep(3)
|
||||
print(f"MAC 地址已更改为: {mac_display}")
|
||||
return True
|
||||
|
||||
|
||||
def get_netsh_interface_name():
|
||||
"""获取 Wi-Fi 网络接口的名称(用于 netsh interface 命令)。"""
|
||||
result = subprocess.run(
|
||||
["netsh", "interface", "show", "interface"],
|
||||
capture_output=True, text=True, encoding="gbk",
|
||||
)
|
||||
for line in result.stdout.splitlines():
|
||||
if "Wi-Fi" in line or "WLAN" in line or "Wireless" in line:
|
||||
parts = line.split()
|
||||
if len(parts) >= 4:
|
||||
return " ".join(parts[3:])
|
||||
return None
|
||||
|
||||
|
||||
def auto_login_wifi():
|
||||
"""自动登录 OSU 公共 Wi-Fi,支持重试。"""
|
||||
edge_options = Options()
|
||||
edge_options.add_argument("--start-maximized")
|
||||
edge_options.add_argument("--ignore-certificate-errors")
|
||||
edge_options.add_argument("--headless")
|
||||
|
||||
for attempt in range(1, MAX_LOGIN_RETRIES + 1):
|
||||
driver = None
|
||||
try:
|
||||
driver = webdriver.Edge(options=edge_options)
|
||||
print(f"第 {attempt} 次尝试登录...")
|
||||
|
||||
# 依次尝试不同的 Captive Portal 触发 URL
|
||||
portal_reached = False
|
||||
for url in CAPTIVE_PORTAL_URLS:
|
||||
print(f" 访问触发页面: {url}")
|
||||
driver.get(url)
|
||||
try:
|
||||
wait = WebDriverWait(driver, 10)
|
||||
wait.until(EC.element_to_be_clickable((By.NAME, "visitor_accept_terms")))
|
||||
portal_reached = True
|
||||
break
|
||||
except Exception:
|
||||
print(f" 未能通过 {url} 跳转到登录页,尝试下一个...")
|
||||
continue
|
||||
|
||||
if not portal_reached:
|
||||
print(f" 第 {attempt} 次尝试未能到达登录页面。")
|
||||
continue
|
||||
|
||||
# 勾选同意协议
|
||||
checkbox = driver.find_element(By.NAME, "visitor_accept_terms")
|
||||
if not checkbox.is_selected():
|
||||
checkbox.click()
|
||||
print(" 已勾选同意协议。")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# 点击登录按钮
|
||||
login_button = driver.find_element(
|
||||
By.XPATH, "//input[@type='submit' and @value='Log In']",
|
||||
)
|
||||
login_button.click()
|
||||
print(" 已点击登录按钮。")
|
||||
|
||||
# 轮询验证是否真正连上网络
|
||||
for i in range(10):
|
||||
time.sleep(2)
|
||||
if is_connected():
|
||||
print("登录成功!网络已连通。")
|
||||
return
|
||||
print(f" 第 {attempt} 次尝试:点击登录后网络仍未连通。")
|
||||
|
||||
except Exception as e:
|
||||
print(f" 第 {attempt} 次尝试出错: {e}")
|
||||
finally:
|
||||
if driver:
|
||||
driver.quit()
|
||||
|
||||
if attempt < MAX_LOGIN_RETRIES:
|
||||
print(" 等待 3 秒后重试...")
|
||||
time.sleep(3)
|
||||
|
||||
print("多次尝试后仍未能成功登录。")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="OSU 公共 Wi-Fi 自动登录工具")
|
||||
parser.add_argument(
|
||||
"--random-mac",
|
||||
action="store_true",
|
||||
help="登录前随机化 Wi-Fi 网卡的 MAC 地址(需要管理员权限)",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if is_connected():
|
||||
print("网络已连接,无需登录。")
|
||||
return
|
||||
|
||||
if args.random_mac:
|
||||
print("正在随机化 MAC 地址...")
|
||||
if not randomize_mac():
|
||||
print("MAC 地址随机化失败,继续尝试登录...")
|
||||
else:
|
||||
# MAC 更改后需要等待 Wi-Fi 重新连接
|
||||
print("等待 Wi-Fi 重新连接...")
|
||||
time.sleep(5)
|
||||
|
||||
auto_login_wifi()
|
||||
from osu_wifi_login.cli import main
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
raise SystemExit(main())
|
||||
|
||||
Reference in New Issue
Block a user