自动登录上海大学校园

项目地址:Github仓库

使用 Python 和 Selenium 编写的自动化脚本,用于自动登录校园网认证系统。

demo 里使用了 Chrome 浏览器与驱动,如否访问外网有困难可以尝试改为使用 Edge 浏览器相关套件,效果应该一样。

示例代码:

python 复制代码
import logging
import shutil
import os
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import time
import subprocess
import traceback

class CampusNetworkLogin:
    def __init__(self) -> None:
        logging.info("启动 Selenium")

        # 禁用系统代理,防止干扰本地驱动连接
        os.environ['no_proxy'] = '*'
        if 'http_proxy' in os.environ: del os.environ['http_proxy']
        if 'https_proxy' in os.environ: del os.environ['https_proxy']

        # 设置 Chrome 选项
        chrome_options = webdriver.ChromeOptions()
        # 指定下载的 chrome.exe 路径
        chrome_options.binary_location = r"D:\XunLei\chrome-win64\chrome.exe"
        # chrome_options.add_argument("--headless") # 重新开启无头模式
        chrome_options.add_argument("--no-sandbox")
        chrome_options.add_argument("--disable-gpu")
        chrome_options.add_argument("--disable-dev-shm-usage")
        # 忽略证书错误和安全警告
        chrome_options.add_argument("--ignore-certificate-errors")
        chrome_options.add_argument("--ignore-ssl-errors")
        chrome_options.add_argument("--allow-running-insecure-content")
        chrome_options.add_argument("--disable-web-security")
        chrome_options.add_argument("--test-type")
        # 允许不安全证书 (Seleinum 4 标准写法)
        chrome_options.set_capability("acceptInsecureCerts", True)
        # 强制将该站点视为安全站点,防止弹出"不安全连接"拦截
        chrome_options.add_argument("--unsafely-treat-insecure-origin-as-secure=http://10.10.9.9,http://123.123.123.123")
        
        # 设置窗口大小,防止 headless 模式下元素重叠或不显示
        chrome_options.add_argument("--window-size=1920,1080")

        try:
            print("正在启动 Chrome...")
            self.driver = webdriver.Chrome(options=chrome_options)
        except Exception as e:
            logging.error(f"启动 Chrome 失败: {e}")
            print("提示:请确保网络正常或驱动已正确下载。")
            exit(1)

    # 登录校园网
    def login_campus_network(self):
        driver = self.driver
        max_attempts = 3
        attempts = 0

        while attempts < max_attempts:
            try:
                print(f"正在访问登录页面... 第 {attempts + 1} 次尝试")
                driver.get('http://10.10.9.9/')
                time.sleep(3) # 等待页面跳转

                # 检查是否已经登录 (根据 HTML, 可能没有 toLogOut,这里可以根据标题判断)
                if "成功" in driver.title or "已经登录" in driver.page_source:
                    print("检测到已经登录成功。")
                    return

                # 登录流程
                try:
                    # 使用 ActionChains 防止普通交互失败
                    actions = ActionChains(driver)

                    print("正在输入用户名...")
                    # 尝试处理用户名提示框遮挡问题
                    try:
                        username_tip = driver.find_element(By.ID, 'username_tip')
                        if username_tip.is_displayed():
                            print("检测到用户名提示遮罩,正在点击...")
                            # 尝试点击遮罩
                            try:
                                username_tip.click()
                            except:
                                actions.click(username_tip).perform()
                            time.sleep(0.5)
                    except:
                        pass

                    username_input = WebDriverWait(driver, 10).until(
                        EC.element_to_be_clickable((By.ID, 'username'))
                    )
                    username_input.clear()
                    # 回退到普通输入方式,防止 ActionChains 在某些情况下失效
                    try:
                         username_input.click()
                         username_input.send_keys('23721830')
                    except:
                         print("普通输入失败,尝试 ActionChains...")
                         actions.click(username_input).send_keys('xxxxxxx').perform()
                    
                    time.sleep(1) # 增加短暂等待

                    print("正在输入密码...")
                    try:
                        pwd_tip = driver.find_element(By.ID, 'pwd_tip')
                        if pwd_tip.is_displayed():
                            print("检测到密码提示遮罩,正在点击...")
                            actions.click(pwd_tip).perform()
                            time.sleep(0.5)
                    except Exception as e:
                        print(f"尝试点击提示遮罩时忽略错误: {e}")

                    password_input = WebDriverWait(driver, 10).until(
                        EC.element_to_be_clickable((By.ID, 'pwd'))
                    )
                    password_input.clear()
                    actions.click(password_input).send_keys('xxxxxxxx').perform()

                    print("正在点击登录按钮...")
                    # 直接点击 a 标签
                    login_button = WebDriverWait(driver, 10).until(
                        EC.element_to_be_clickable((By.ID, 'loginLink'))
                    )
                    # login_button.click()
                    actions.click(login_button).perform()

                    # 等待登录结果
                    time.sleep(5)
                    if self.check_network_connection():
                        print("校园网登录成功!")
                        return
                    else:
                        print("登录后网络仍未通,可能账户密码错误或欠费。")
                        driver.save_screenshot('error_result.png')
                
                except Exception as e:
                    print(f"操作页面元素时出错: {e}")
                    traceback.print_exc()
                    driver.save_screenshot(f'error_step_{attempts}.png')
                    attempts += 1

            except Exception as e:
                print(f"页面加载出错: {e}")
                attempts += 1
            
            time.sleep(2)

        print("达到最大尝试次数,登录失败。")

    # 检查网络是否可以 ping 通百度
    def check_network_connection(self):
        try:
            # Windows 下 ping 参数是 -n
            result = subprocess.run(['ping', '-n', '1', 'www.baidu.com'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            return result.returncode == 0
        except Exception as e:
            print(f"检查网络连接时出错: {e}")
            return False

    # 检查网络连接状态
    def check_and_login(self):
        if self.check_network_connection():
            print("网络连接正常,无需登录。")
        else:
            print("网络无法连接,尝试登录校园网...")
            self.login_campus_network()

# 创建 CampusNetworkLogin 实例并调用 check_and_login 函数
campus_network = CampusNetworkLogin()
campus_network.check_and_login()
相关推荐
Vect__16 小时前
基于线程池从零实现TCP计算器网络服务
c++·网络协议·tcp/ip
wenzhangli721 小时前
OoderAgent SDK(0.6.6) UDP通讯与协议测试深度解析
网络·网络协议·udp
好家伙VCC1 天前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
前端玖耀里1 天前
如何使用python的boto库和SES发送电子邮件?
python
serve the people1 天前
python环境搭建 (十二) pydantic和pydantic-settings类型验证与解析
java·网络·python
小天源1 天前
Error 1053 Error 1067 服务“启动后立即停止” Java / Python 程序无法后台运行 windows nssm注册器下载与报错处理
开发语言·windows·python·nssm·error 1053·error 1067
喵手1 天前
Python爬虫实战:HTTP缓存系统深度实战 — ETag、Last-Modified与requests-cache完全指南(附SQLite持久化存储)!
爬虫·python·爬虫实战·http缓存·etag·零基础python爬虫教学·requests-cache
喵手1 天前
Python爬虫实战:容器化与定时调度实战 - Docker + Cron + 日志轮转 + 失败重试完整方案(附CSV导出 + SQLite持久化存储)!
爬虫·python·爬虫实战·容器化·零基础python爬虫教学·csv导出·定时调度
2601_949146531 天前
Python语音通知接口接入教程:开发者快速集成AI语音API的脚本实现
人工智能·python·语音识别
寻梦csdn1 天前
pycharm+miniconda兼容问题
ide·python·pycharm·conda