from dataclasses import dataclass
import time
from datetime import datetime
from pathlib import Path
from typing import List
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.remote.webelement import WebElement
from contextlib import contextmanager
import tkinter as tk
@dataclass
class EmailInfo:
text: str
element: WebElement
@dataclass
class DownloadConfig:
folder_name: str
patterns: List[str]
@dataclass
class LoginConfig:
"""登录配置"""
base_url: str = "http://10.190.188.246/nsmail/index.html#login"
username: str = "gwjxd_zhzx"
password: str = "ZHzx@1108"
class RevealDownloader:
def __init__(self):
self.today = datetime.now()
self.month = str(self.today.month).lstrip('0')
self.day = str(self.today.day).lstrip('0')
self.base_path = Path('E:/GYK运行揭示1.5编辑')
self.date_folder = f'{self.month}月{self.day}日揭示上午版'
self.login_config = LoginConfig()
self.setup_download_configs()
self.driver = self.setup_chrome_driver()
def setup_download_configs(self) -> None:
"""设置下载配置"""
self.download_configs = {
'liuji': DownloadConfig(
folder_name=f'4-柳机({self.month}月{self.day}日上午版)',
patterns=[f"{self.month}月{self.day}日上午运行揭示正式版", f"{self.month}月{self.day}日上午运行揭示正式版(无新令)"]
),
'changguibao': DownloadConfig(
folder_name=f'5-长轨包({self.month}月{self.day}日上午版)',
patterns=[f"{self.month}月{self.day}日上午全线长轨达示包", f"{self.month}月{self.day}日上午工机段全线长轨达示包"]
)
}
def setup_chrome_driver(self) -> webdriver.Chrome:
"""配置Chrome浏览器"""
options = Options()
options.binary_location = r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chrome.exe"
options.add_argument("--disable-extensions")
options.add_argument("--no-sandbox")
options.add_argument("--disable-gpu")
options.add_argument('--lang=zh-CN')
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
prefs = {
"profile.default_content_setting_values.automatic_downloads": 1,
"download.prompt_for_download": False,
"download.directory_upgrade": True,
"safebrowsing.enabled": True
}
options.add_experimental_option("prefs", prefs)
service = Service(r"D:\软件安装\特殊\Chrome 懒人绿色版\Chrome\chromedriver.exe")
return webdriver.Chrome(service=service, options=options)
def wait_for_element(self, by: By, value: str, timeout: int = 10) -> WebElement:
"""等待元素加载"""
wait = WebDriverWait(self.driver, timeout)
return wait.until(EC.presence_of_element_located((by, value)))
def wait_for_clickable_element(self, by: By, value: str, timeout: int = 10) -> WebElement:
"""等待元素可点击"""
wait = WebDriverWait(self.driver, timeout)
return wait.until(EC.element_to_be_clickable((by, value)))
def login(self) -> bool:
"""登录到邮箱系统"""
try:
print("\n开始登录邮箱系统...")
# 访问登录页面
print(f"访问登录页面: {self.login_config.base_url}")
self.driver.get(self.login_config.base_url)
time.sleep(8) # 增加等待时间,让页面完全加载
print("页面加载完成,开始查找元素...")
# 首先检查页面是否正确加载
print(f"当前页面标题: {self.driver.title}")
print(f"当前页面URL: {self.driver.current_url}")
# 搜索所有可能的输入框
print("\n搜索页面中的输入框...")
all_inputs = self.driver.find_elements(By.TAG_NAME, "input")
print(f"找到 {len(all_inputs)} 个输入框:")
username_field = None
password_field = None
for i, input_elem in enumerate(all_inputs):
try:
input_id = input_elem.get_attribute("id") or "无ID"
input_type = input_elem.get_attribute("type") or "无类型"
input_placeholder = input_elem.get_attribute("placeholder") or "无placeholder"
input_name = input_elem.get_attribute("name") or "无name"
print(f" 输入框{i+1}: ID='{input_id}', type='{input_type}', placeholder='{input_placeholder}', name='{input_name}'")
# 识别用户名输入框
if (input_id == "username" or
"邮箱账号" in input_placeholder or
"username" in input_name.lower() or
"user" in input_id.lower()):
username_field = input_elem
print(f" -> 识别为用户名输入框")
# 识别密码输入框
elif (input_id == "password" or
input_type == "password" or
"密码" in input_placeholder or
"password" in input_name.lower()):
password_field = input_elem
print(f" -> 识别为密码输入框")
except Exception as e:
print(f" 检查输入框{i+1}时出错: {e}")
# 输入用户名
if username_field:
print(f"\n开始输入用户名: {self.login_config.username}")
try:
# 多种输入方式
self.driver.execute_script("arguments[0].focus();", username_field)
username_field.clear()
time.sleep(0.5)
username_field.send_keys(self.login_config.username)
time.sleep(0.5)
# 验证输入结果
entered_value = username_field.get_attribute("value")
print(f"用户名输入结果: '{entered_value}'")
if entered_value != self.login_config.username:
print("用户名输入不完整,尝试JS输入...")
self.driver.execute_script(f"arguments[0].value = '{self.login_config.username}';", username_field)
# 触发输入事件
self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", username_field)
except Exception as e:
print(f"输入用户名时出错: {e}")
else:
print("❌ 未找到用户名输入框")
return False
# 输入密码
if password_field:
print(f"\n开始输入密码...")
try:
self.driver.execute_script("arguments[0].focus();", password_field)
password_field.clear()
time.sleep(0.5)
password_field.send_keys(self.login_config.password)
time.sleep(0.5)
# 验证密码是否输入(密码框通常不会显示实际值)
entered_value = password_field.get_attribute("value")
print(f"密码输入长度: {len(entered_value) if entered_value else 0}")
if not entered_value or len(entered_value) == 0:
print("密码输入失败,尝试JS输入...")
self.driver.execute_script(f"arguments[0].value = '{self.login_config.password}';", password_field)
self.driver.execute_script("arguments[0].dispatchEvent(new Event('input', { bubbles: true }));", password_field)
except Exception as e:
print(f"输入密码时出错: {e}")
else:
print("❌ 未找到密码输入框")
return False
# 查找登录按钮
print("\n搜索登录按钮...")
login_button = None
# 搜索所有可能的按钮元素
button_selectors = [
("按钮标签", "//button"),
("输入按钮", "//input[@type='button' or @type='submit']"),
("包含登录的元素", "//*[contains(text(), '登录')]"),
("class包含btn的元素", "//*[contains(@class, 'btn')]"),
("class包含log的元素", "//*[contains(@class, 'log')]"),
("p标签", "//p")
]
for desc, selector in button_selectors:
try:
elements = self.driver.find_elements(By.XPATH, selector)
print(f" {desc}: 找到 {len(elements)} 个")
for elem in elements:
try:
text = elem.text.strip()
class_name = elem.get_attribute("class") or ""
tag_name = elem.tag_name
if text or "btn" in class_name.lower() or "log" in class_name.lower():
print(f" - {tag_name}: '{text}', class='{class_name}'")
if ("登录" in text or "log" in class_name.lower()) and not login_button:
login_button = elem
print(f" -> 选择为登录按钮")
except:
pass
except Exception as e:
print(f" 搜索{desc}时出错: {e}")
# 点击登录按钮
if login_button:
print(f"\n点击登录按钮...")
try:
# 滚动到按钮位置
self.driver.execute_script("arguments[0].scrollIntoView(true);", login_button)
time.sleep(1)
# 尝试点击
self.driver.execute_script("arguments[0].click();", login_button)
print("已点击登录按钮")
time.sleep(8)
except Exception as e:
print(f"点击登录按钮时出错: {e}")
return False
else:
print("❌ 未找到登录按钮")
return False
# 检查登录结果
print("\n检查登录结果...")
current_url = self.driver.current_url
print(f"登录后URL: {current_url}")
if self.check_login_success():
print("✓ 登录成功!")
return True
else:
print("❌ 登录失败")
return False
except Exception as e:
print(f"登录过程出现异常: {str(e)}")
import traceback
traceback.print_exc()
return False
def check_login_success(self) -> bool:
"""检查登录是否成功"""
try:
# 增加等待时间
time.sleep(5)
print("检查登录状态...")
# 方法1: 检查URL是否发生变化
current_url = self.driver.current_url
if "login" not in current_url.lower():
print("URL已改变,登录可能成功")
return True
# 方法2: 检查是否有错误提示
error_elements = self.driver.find_elements(By.XPATH, "//*[contains(text(), '错误') or contains(text(), '失败') or contains(text(), '用户名') or contains(text(), '密码')]")
if error_elements:
for error in error_elements:
error_text = error.text.strip()
if error_text and any(keyword in error_text for keyword in ['错误', '失败', '不正确', '无效']):
print(f"发现错误信息: {error_text}")
return False
# 方法3: 检查是否不再有登录表单
login_forms = self.driver.find_elements(By.ID, "username")
if not login_forms:
print("登录表单已消失,登录成功")
return True
# 方法4: 检查是否有登录后的特征元素
# 邮件系统通常会有菜单、导航或者邮箱相关元素
success_indicators = [
"//span[contains(text(), '邮件')]",
"//div[contains(@class, 'mail') or contains(@class, 'inbox')]",
"//*[contains(text(), '收件箱') or contains(text(), '发件箱')]",
"//a[contains(@href, 'mail') or contains(@href, 'inbox')]"
]
for xpath in success_indicators:
elements = self.driver.find_elements(By.XPATH, xpath)
if elements:
print(f"发现登录成功标志元素: {xpath}")
return True
# 方法5: 检查页面标题
page_title = self.driver.title
if page_title and "登录" not in page_title and "login" not in page_title.lower():
print(f"页面标题已改变: {page_title}")
return True
print("未能确认登录状态")
return False
except Exception as e:
print(f"检查登录状态时出错: {e}")
return False
def click_mail_menu(self) -> bool:
"""点击邮件菜单"""
try:
print("点击邮件菜单...")
mail_span = self.wait_for_clickable_element(
By.XPATH,
"//span[contains(text(), '邮件')]"
)
self.driver.execute_script("arguments[0].click();", mail_span)
time.sleep(3)
print("✓ 成功点击邮件菜单")
return True
except Exception as e:
print(f"点击邮件菜单失败: {e}")
return False
def click_inbox(self) -> bool:
"""点击收件箱"""
try:
print("点击收件箱...")
inbox_element = self.wait_for_clickable_element(
By.XPATH,
"//div[contains(@class, 'to_inbox') and contains(text(), '收邮件')]"
)
self.driver.execute_script("arguments[0].click();", inbox_element)
time.sleep(3)
print("✓ 成功点击收件箱")
return True
except Exception as e:
print(f"点击收件箱失败: {e}")
return False
def run_login_test(self) -> None:
"""运行登录测试"""
try:
print("开始登录测试...")
print(f"目标网址: {self.login_config.base_url}")
print(f"用户名: {self.login_config.username}")
print(f"密码: {'*' * len(self.login_config.password)}")
if self.login():
print("✓ 登录成功!")
# 等待一下,让页面完全加载
time.sleep(3)
# 打印当前页面信息用于调试
print(f"当前页面标题: {self.driver.title}")
print(f"当前页面URL: {self.driver.current_url}")
# 尝试寻找页面上的关键元素
print("\n搜索页面关键元素...")
key_selectors = [
("邮件相关", "//span[contains(text(), '邮件')]"),
("收件箱", "//*[contains(text(), '收件箱')]"),
("菜单项", "//div[@class]//span | //li//span | //a//span"),
("按钮", "//button | //input[@type='button'] | //div[@class*='btn']")
]
for name, selector in key_selectors:
try:
elements = self.driver.find_elements(By.XPATH, selector)
if elements:
print(f" 找到{name}: {len(elements)}个")
for i, elem in enumerate(elements[:3]): # 只显示前3个
try:
text = elem.text.strip()
if text:
print(f" {i+1}. {text}")
except:
pass
else:
print(f" 未找到{name}")
except Exception as e:
print(f" 搜索{name}时出错: {e}")
print("\n登录测试完成!")
print("请查看浏览器窗口确认登录状态")
print("按回车键继续...")
input()
else:
print("✗ 登录失败")
print("请检查:")
print("1. 网址是否正确")
print("2. 用户名和密码是否正确")
print("3. 网络连接是否正常")
except Exception as e:
print(f"登录测试出错: {e}")
import traceback
traceback.print_exc()
finally:
print("5秒后关闭浏览器...")
time.sleep(5)
self.driver.quit()
if __name__ == '__main__':
try:
RevealDownloader().run_login_test()
except Exception as e:
print(f"程序执行失败: {e}")
time.sleep(3)
账号和密码输入没有问题,就是”登录”按钮,点击不了,实现不了登录