1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
|
import subprocess
import requests
import os
import time
import sys
from bs4 import BeautifulSoup as bs
from time import sleep
# 错误代码
# 0x01 : 未配置用户名
# 0x02 : 未连接到目标WIFI
# 0x03 : 未获取到IPv4地址
# 0x04 : 获取paramStr失败
# 0x05 : 认证失败
# 0x06 : 认证失败,凭据错误
# 默认用户名和密码
# 如果环境变量中设置了ChinaUnicom_WIFI_USERNAME和ChinaUnicom_WIFI_PASSWORD,则使用这些值
# 如果提供未修改的密码,则自动生成用户名
# 如果环境变量中没有设置,则使用默认值
DEF_UserName = None
DEF_PassWord = None
if DEF_UserName is None or DEF_PassWord is None:
USERNAME = os.getenv("ChinaUnicom_WIFI_USERNAME")
PASSWORD = os.getenv("ChinaUnicom_WIFI_PASSWORD")
else:
USERNAME = os.getenv("ChinaUnicom_WIFI_USERNAME", DEF_UserName)
PASSWORD = os.getenv("ChinaUnicom_WIFI_PASSWORD", DEF_PassWord)
if USERNAME is None or PASSWORD is None:
USERID = sys.argv[1] if len(sys.argv) > 1 else None
if USERID is not None:
USERNAME = "02505" + USERID
PASSWORD = USERID
# 日志文件
LOGFILE = "auth.log"
LOG_LIMIT = 300
# 判断日志行数并删除旧日志
def clean_log():
if os.path.exists(LOGFILE):
with open(LOGFILE, "r", encoding="utf-8") as log_file:
lines = log_file.readlines()
if len(lines) > LOG_LIMIT:
with open(LOGFILE, "w", encoding="utf-8") as log_file:
log_file.writelines(lines[-LOG_LIMIT:])
# 日志记录函数
def logger(message):
print(message)
with open(LOGFILE, "a", encoding="utf-8") as log_file:
log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {message}\n")
def end_process(message, error_code=0):
logger(message)
exit(error_code)
clean_log()
logger("程序启动,开始自动认证流程。")
# 检查用户名和密码是否配置
if USERNAME is None or PASSWORD is None:
end_process("未配置用户名或密码,程序退出。", 0x01)
# 测试网络连接
CHCP_CMD = "chcp 65001"
PING_TEST_URL = "www.bing.com"
PING_TEST_CMD = f"ping -n 1 {PING_TEST_URL}"
PING_TEST_CMD = f"{CHCP_CMD} && {PING_TEST_CMD}"
def ping_test():
try:
result = subprocess.run(PING_TEST_CMD, shell=True, capture_output=True, text=True)
if "TTL=" in result.stdout:
return True
else:
return False
except Exception as e:
logger(f"网络连接测试失败: {e}")
return False
# ------ 检查网络连接 ------
if ping_test():
end_process("网络连接正常,无需认证。", 0)
# 获取连接的WIFI名称
GET_WIFI_CMD = "netsh wlan show interfaces"
GET_WIFI_CMD = f"{CHCP_CMD} && {GET_WIFI_CMD}"
ATTR_WIFI_KEYWORD = "SSID"
def get_current_wifi():
try:
result = subprocess.run(GET_WIFI_CMD, shell=True, capture_output=True, text=True)
if result.returncode != 0:
return None
output = result.stdout
for line in output.splitlines():
if ATTR_WIFI_KEYWORD in line:
return line.split(":")[1].strip()
except Exception as e:
logger(f"无法获取WiFi名称: {e}")
return None
# 检查当前连接的WIFI是否为目标WIFI
DST_WIFI = "ChinaUnicom"
RETRY_TIME = 3
RETRY_COUNT = 3
def check_wifi():
current_wifi = get_current_wifi()
if current_wifi != DST_WIFI:
logger(f"当前WiFi SSID: {current_wifi}. 等待连接到 {DST_WIFI}...")
return False
logger(f"已连接到 {DST_WIFI}.")
return True
# ------ 等待连接到目标WIFI ------
while not check_wifi():
sleep(RETRY_TIME)
RETRY_COUNT -= 1
if RETRY_COUNT <= 0:
end_process(f"未连接到目标WIFI {DST_WIFI},请检查网络设置。", 0x02)
# 获取当前IPv4地址
GET_IP_CMD = "ipconfig"
GET_IP_CMD = f"{CHCP_CMD} && {GET_IP_CMD}"
DST_ADAPTERS = ["无线局域网适配器 WLAN", "Wireless LAN adapter WLAN"]
END_KEYWORD = "适配器"
ATTR_IPV4_KEYWORD = ["IPv4 地址", "IPv4 Address"]
RETRY_TIME2 = 3
RETRY_COUNT2 = 3
def get_wifi_ip():
try:
result = subprocess.run(GET_IP_CMD, shell=True, capture_output=True, text=True)
if result.returncode != 0:
return None
output = result.stdout
lines = output.splitlines()
wlan_section = False
for line in lines:
if any(adapter in line for adapter in DST_ADAPTERS):
wlan_section = True
continue
elif END_KEYWORD in line and wlan_section:
break
elif wlan_section and any(keyword in line for keyword in ATTR_IPV4_KEYWORD):
ip = line.split(":")[-1].strip()
return ip
except Exception as e:
logger(f"无法获取IPv4地址: {e}")
return None
# ------ 获取当前IPv4地址 ------
CRT_IP = get_wifi_ip()
while not CRT_IP:
logger("无法获取当前IPv4地址, 正在重试...")
sleep(RETRY_TIME2)
CRT_IP = get_wifi_ip()
RETRY_COUNT2 -= 1
if RETRY_COUNT2 <= 0:
end_process("未获取到IPv4地址, 请检查网络设置。", 0x03)
logger(f"当前IPv4地址: {CRT_IP}")
# ------ 再次检查网络连接 ------
if ping_test():
end_process("网络连接正常,无需认证。", 0)
# 获取连接所需的参数
BASE_URL = "http://58.240.51.118"
PAGE_URL = BASE_URL + "/?wlanuserip=" + str(CRT_IP) + "&basname=&ssid=school"
def get_paramStr():
# 主页面
page_info = requests.request("GET", PAGE_URL)
if page_info.status_code != 200:
return None
page_context = page_info.text
soup = bs(page_context, "html.parser")
main_frame = soup.find("frame", {"name": "mainFrame"})
if not main_frame:
return None
frame_src = main_frame["src"] # type: ignore
# 子页面
frame_url = BASE_URL + str(frame_src)
page_info2 = requests.request("GET", frame_url)
if page_info2.status_code != 200:
return None
page_context2 = page_info2.text
soup2 = bs(page_context2, "html.parser")
paramStr_input = soup2.find("input", {"name": "paramStr"})
paramStr = paramStr_input["value"] # type: ignore
return paramStr
# 自动认证
PROVINCE = "wlan.js.chinaunicom.cn"
GDYH = "prov"
URL = BASE_URL + "/authServlet"
SUCCESS_KEYWORD = "本次上网时长:"
# ------- 自动认证 --------
try:
paramStr = get_paramStr()
if paramStr is None:
raise ValueError("无法从页面获取paramStr。")
except Exception as e:
end_process(f"获取paramStr失败: {e}", 0x04)
FORM_DATA = {
"province": PROVINCE,
"paramStr": paramStr,
"gdyh": GDYH,
"shortname": "",
"UserName": USERNAME,
"PassWord": PASSWORD,
}
response = requests.request("POST", URL, data=FORM_DATA)
if response.status_code == 200:
logger("收到响应,正在检查认证结果...")
if not SUCCESS_KEYWORD in response.text:
end_process("认证失败,请检查您的凭据。", 0x06)
else:
end_process(f"认证失败,状态码: {response.status_code}", 0x05)
logger(f"认证成功,已完成自动认证。用户名: {USERNAME}, IPv4地址: {CRT_IP}")
# 防止连续多次触发
sleep(10)
logger("程序结束,等待下次触发。")
|