217. Contains Duplicate--Python

本文介绍了一种检查整数数组中是否存在重复元素的有效方法。通过对比数组长度与其唯一元素集合的大小来判断是否有重复项,提供了一个简洁高效的解决方案。

217Contains Duplicate

Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.


我的版本:

class Solution:
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        nums.sort()
        if len(nums)>1:
            if nums[0] == nums[-1]:
                return True
            else:
                L=list(set(range(nums[0], nums[-1] + 1)).difference(set(nums)))
                if  len(L)==nums[-1]-nums[0]+1-len(nums):
                    return False
                else:
                    return True
        else:
            return False
之前不了解set()的用法,上面的版本是在之前寻找消失的数(第448题)中使用的方法直接稍加改动搬过来的,也可以被接受不过多少还是绕了很大的弯子,在了解的set()的用法以后可以用下面的精简版即可!

精简版:

class Solution:
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        if len(set(nums)) == len(nums):
            return False
        else:
            return True


217Contains Duplicate
from selenium import webdriver 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.common.exceptions import TimeoutException import datetime import time import sys import os import glob import re def clear_download_dir(download_dir): # 要删除的文件类型 patterns = ["*.xlsx", "*.xls", "*.csv", "*.pdf"] # 可根据需要扩展 deleted_count = 0 for pattern in patterns: file_list = glob.glob(os.path.join(download_dir, pattern)) for file_path in file_list: os.remove(file_path) print(f"已删除: {os.path.basename(file_path)}") deleted_count += 1 else: print(f"文件不存在") if deleted_count == 0: print("✅ 下载目录为空,无需清理") else: print(f"🧹 共清理 {deleted_count} 个旧文件") def load_all_operations(module): combined = {} for attr_name in dir(module): if attr_name.startswith("OPERATIONS_"): obj = getattr(module, attr_name) if isinstance(obj, dict): duplicate_keys = set(obj.keys()) & set(combined.keys()) if duplicate_keys: print(f"⚠️ 警告: '{attr_name}' 包含重复任务名: {duplicate_keys} → 将被覆盖") combined.update(obj) print(f"✅ 加载操作集: {attr_name} ({len(obj)} 项)") else: print(f"❌ 跳过非字典成员: {attr_name}") return combined # ======================================== class EnergySystemLogin: def __init__(self): self.login_url = "http://10.11.20.117:7001/energy4/#/login" self.credentials = {'username': 'E915285', 'password': '123456'} self.driver = None self.wait_timeout = 30 def initialize_driver(self): """初始化Chrome浏览器(无头模式 + 支持文件下载)""" try: options = webdriver.ChromeOptions() # --- 反检测设置 --- options.add_argument("--disable-blink-features=AutomationControlled") options.add_argument("--start-maximized") options.add_argument("--headless=new") # 新版无头模式 options.add_argument("--disable-gpu") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") options.add_argument("--window-size=1920,1080") options.add_argument("--log-level=3") # 关闭自动化控制提示 options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option("useAutomationExtension", False) # 下载目录配置 download_dir = r"D:\Class\能管比对\导出文件" if not os.path.exists(download_dir): os.makedirs(download_dir) prefs = { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True, "profile.default_content_settings.popups": 0, "plugins.always_open_pdf_externally": False, } options.add_experimental_option("prefs", prefs) self.driver = webdriver.Chrome(options=options) self.driver.implicitly_wait(10) # 防止被识别为机器人 self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => false});") self.log_action(f"浏览器初始化完成,下载路径: {download_dir}") return True except: pass def log_action(self, message): timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"[{timestamp}] {message}") def log_error(self, message): timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') print(f"[{timestamp}] 错误: {message}") def locate_and_input(self, by, value, text, description): try: element = WebDriverWait(self.driver, self.wait_timeout).until( EC.visibility_of_element_located((by, value)) ) element.clear() element.send_keys(text) self.log_action(f"{description} 输入完成") return True except: pass def perform_login(self): try: self.log_action("访问登录页面") self.driver.get(self.login_url) # 等待页面加载完成 WebDriverWait(self.driver, self.wait_timeout).until( lambda d: d.execute_script("return document.readyState") == "complete" ) # 输入用户名 if not self.locate_and_input( By.CSS_SELECTOR, "input.el-input__inner[type='text']", self.credentials['username'], "用户名" ): return False # 输入密码 if not self.locate_and_input( By.CSS_SELECTOR, "input.el-input__inner[type='password']", self.credentials['password'], "密码" ): return False # 点击登录按钮 try: login_btn = WebDriverWait(self.driver, self.wait_timeout).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "button.loginBtn")) ) login_btn.click() self.log_action("点击登录按钮") except Exception as e: self.log_error(f"点击登录按钮失败: {str(e)}") return False # 等待登录成功跳转 try: WebDriverWait(self.driver, 20).until( EC.url_contains("/energy4/#/") ) WebDriverWait(self.driver, 10).until_not( EC.presence_of_element_located((By.CLASS_NAME, "login-container")) ) self.log_action("登录成功") self.driver.save_screenshot("login_success.png") return True except TimeoutException: self.log_error("登录验证超时,可能未成功登录") return False except Exception as e: self.log_error(f"登录过程发生异常: {str(e)}") return False def get_driver(self): return self.driver def cleanup(self): if self.driver: try: self.driver.quit() except Exception as e: print(f"清理浏览器资源时出错: {str(e)}") # ======================================== class MenuNavigator: def __init__(self, driver, operations_dict, download_dir=r"D:\Class\能管比对\导出文件"): self.driver = driver self.wait_timeout = 10 self.click_delay = 3 self.download_dir = download_dir self.OPERATIONS = operations_dict # 接收外部传入的所有操作流程 def get_timestamp(self): return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') def log_action(self, message): print(f"[{self.get_timestamp()}] 操作: {message}") def log_error(self, message): print(f"[{self.get_timestamp()}] 错误: {message}") try: print("有点问题") except: pass def click_element(self, xpath, description): try: element = WebDriverWait(self.driver, self.wait_timeout).until( EC.visibility_of_element_located((By.XPATH, xpath)) ) element.click() self.log_action(f"点击成功: {description}") time.sleep(self.click_delay) # 固定等待页面响应 return True except Exception as e: self.log_error(f"点击失败 ({description}): {str(e)}") return False def get_latest_downloaded_file(self, timeout=30): """等待并返回最新稳定的 .xlsx 文件""" start_time = time.time() while time.time() - start_time < timeout: list_of_files = [ f for f in glob.glob(os.path.join(self.download_dir, "*.xls*")) if not os.path.basename(f).startswith("~$") ] if list_of_files: latest_file = max(list_of_files, key=os.path.getmtime) size1 = os.path.getsize(latest_file) time.sleep(1) size2 = os.path.getsize(latest_file) if size1 == size2: # 大小稳定表示写入完成 return latest_file time.sleep(1) raise Exception("等待下载超时,未检测到新文件") def extract_filename(self, task_key): filename = f"{task_key}.xlsx" return filename def rename_latest_file(self, new_name): """将最新下载的文件重命名为指定名称,避免覆盖""" try: old_file = self.get_latest_downloaded_file() new_file_path = os.path.join(self.download_dir, new_name) counter = 1 base_name, ext = os.path.splitext(new_name) while os.path.exists(new_file_path): new_file_path = os.path.join(self.download_dir, f"{base_name}_{counter}{ext}") counter += 1 os.rename(old_file, new_file_path) self.log_action(f"文件已重命名: {os.path.basename(old_file)} → {os.path.basename(new_file_path)}") return True except Exception as e: self.log_error(f"文件重命名失败: {str(e)}") return False def navigate(self, task_key): """执行单个任务流程""" if task_key not in self.OPERATIONS: self.log_error(f"未找到名为 '{task_key}' 的操作流程") return False operations = self.OPERATIONS[task_key] self.log_action(f"开始执行任务: {task_key}") for op in operations: if not self.click_element(op["xpath"], op["desc"]): self.log_error(f"操作中断于: {op['desc']}") return False # 🔁 判断是否为预操作:不需要导出文件 if task_key == "0.预操作": self.log_action("✅ 任务 '0.预操作' 执行完成(无导出动作)") return True # 其他任务继续走导出逻辑 auto_filename = self.extract_filename(task_key) self.log_action("正在等待导出文件生成...") if self.rename_latest_file(auto_filename): self.log_action(f"✅ 任务 '{task_key}' 成功,文件已保存为: {auto_filename}") return True else: self.log_error(f"❌ 任务 '{task_key}' 失败:无法获取或重命名导出文件") return False def wait_for_file_stable(self, file_path, timeout=10): """等待指定文件大小不再变化""" if not os.path.exists(file_path): return try: size1 = os.path.getsize(file_path) for _ in range(timeout): time.sleep(1) if not os.path.exists(file_path): break size2 = os.path.getsize(file_path) if size1 == size2: break size1 = size2 except Exception as e: self.log_error(f"检查文件稳定性时出错: {str(e)}") if __name__ == "__main__": login = None download_dir = r"D:\Class\能管比对\导出文件" # ← 统一管理路径 clear_download_dir(download_dir) try: login = EnergySystemLogin() driver = login.get_driver() # 🔍 支持加载多个 operations 模块 module_names = [ "menu_operations0", # "menu_operations1", # "menu_operations2", # "menu_operations3", "menu_operations4", ] ALL_OPERATIONS = {} for mod_name in module_names: try: module = __import__(mod_name) import importlib importlib.reload(module) combined_in_mod = load_all_operations(module) duplicate_keys = set(combined_in_mod.keys()) & set(ALL_OPERATIONS.keys()) if duplicate_keys: print(f"⚠️ 跨模块重复任务名: {duplicate_keys} → 将被后加载的覆盖") ALL_OPERATIONS.update(combined_in_mod) print(f"📁 已从模块 '{mod_name}' 加载 {len(combined_in_mod)} 项任务\n") except: break navigator = MenuNavigator(driver, operations_dict=ALL_OPERATIONS) tasks_to_run = list(ALL_OPERATIONS.keys()) print(f"\n📋 共发现 {len(tasks_to_run)} 个待执行任务:") for i, task in enumerate(tasks_to_run, 1): print(f" {i}. {task}") success_count = 0 for task in tasks_to_run: print(f"\n🔁 正在执行任务: {task}") if navigator.navigate(task): success_count += 1 else: print(f"任务 '{task}' 执行失败") print(f"\n🎉 总结:{success_count}/{len(tasks_to_run)} 个任务执行成功") except KeyboardInterrupt: print("\n\n🛑 用户手动中断程序") except Exception as e: print(f"🚨 程序发生未预期异常: {str(e)}") finally: if login: login.cleanup() print("🔚 程序结束") ——"D:\Program Files\Python39\python.exe" C:\Users\E918928\PycharmProjects\pythonProject\LZRR\代码1、\能管检查\去OPERATE.py 文件不存在 文件不存在 文件不存在 文件不存在 ✅ 下载目录为空,无需清理 ✅ 加载操作集: OPERATIONS_0 (1 项) 📁 已从模块 'menu_operations0' 加载 1 项任务 ✅ 加载操作集: OPERATIONS_4 (23 项) 📁 已从模块 'menu_operations4' 加载 23 项任务 📋 共发现 24 个待执行任务: 1. 0.预操作 2. 70.电系统-行政、后勤类-生活类 3. 71.电系统-行政、后勤类-办公类 4. 72.电系统-行政、后勤类-其他辅助类 5. 73.电系统-工艺类-FAB1 6. 74.电系统-工艺类-OS1 Wafersort 7. 75.电系统-工艺类-实验室 8. 76.电系统-厂务类-AC 9. 77.电系统-厂务类-GC 10. 78.电系统-厂务类-water 11. 79.电系统-厂务类-Elec 12. 80.电系统-厂务类-CFC 13. 81.电系统-大宗气站-大宗气站1 14. 82.电系统-大宗气站-大宗气站2 15. 83.FAB 16. 84.电系统-220Kv PS1a-CUB 17. 85.电系统-220Kv PS1a-WWT 18. 86.电系统-220Kv PS1a-OS 19. 87.电系统-220Kv PS1a-ADB 20. 88.电系统-220Kv PS1a-XDH 21. 89.电系统-220Kv PS1a-生活区 22. 90.电系统-220Kv PS1a-未来馆 23. 91.电系统-工艺厂务能耗比 24. 92.电系统-工艺+厂务耗电量 🔁 正在执行任务: 0.预操作 [2025-11-05 11:14:29] 操作: 开始执行任务: 0.预操作 [2025-11-05 11:14:29] 错误: 点击失败 (能耗统计): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 能耗统计 有点问题 任务 '0.预操作' 执行失败 🔁 正在执行任务: 70.电系统-行政、后勤类-生活类 [2025-11-05 11:14:29] 操作: 开始执行任务: 70.电系统-行政、后勤类-生活类 [2025-11-05 11:14:29] 错误: 点击失败 (电系统): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 电系统 有点问题 任务 '70.电系统-行政、后勤类-生活类' 执行失败 🔁 正在执行任务: 71.电系统-行政、后勤类-办公类 [2025-11-05 11:14:29] 操作: 开始执行任务: 71.电系统-行政、后勤类-办公类 [2025-11-05 11:14:29] 错误: 点击失败 (办公类): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 办公类 有点问题 任务 '71.电系统-行政、后勤类-办公类' 执行失败 🔁 正在执行任务: 72.电系统-行政、后勤类-其他辅助类 [2025-11-05 11:14:29] 操作: 开始执行任务: 72.电系统-行政、后勤类-其他辅助类 [2025-11-05 11:14:29] 错误: 点击失败 (其他辅助类): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 其他辅助类 有点问题 任务 '72.电系统-行政、后勤类-其他辅助类' 执行失败 🔁 正在执行任务: 73.电系统-工艺类-FAB1 [2025-11-05 11:14:29] 操作: 开始执行任务: 73.电系统-工艺类-FAB1 [2025-11-05 11:14:29] 错误: 点击失败 (工艺类): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 工艺类 有点问题 任务 '73.电系统-工艺类-FAB1' 执行失败 🔁 正在执行任务: 74.电系统-工艺类-OS1 Wafersort [2025-11-05 11:14:29] 操作: 开始执行任务: 74.电系统-工艺类-OS1 Wafersort [2025-11-05 11:14:29] 错误: 点击失败 (OS1 Wafersort): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: OS1 Wafersort 有点问题 任务 '74.电系统-工艺类-OS1 Wafersort' 执行失败 🔁 正在执行任务: 75.电系统-工艺类-实验室 [2025-11-05 11:14:29] 操作: 开始执行任务: 75.电系统-工艺类-实验室 [2025-11-05 11:14:29] 错误: 点击失败 (实验室): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 实验室 有点问题 任务 '75.电系统-工艺类-实验室' 执行失败 🔁 正在执行任务: 76.电系统-厂务类-AC [2025-11-05 11:14:29] 操作: 开始执行任务: 76.电系统-厂务类-AC [2025-11-05 11:14:29] 错误: 点击失败 (厂务类): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 厂务类 有点问题 任务 '76.电系统-厂务类-AC' 执行失败 🔁 正在执行任务: 77.电系统-厂务类-GC [2025-11-05 11:14:29] 操作: 开始执行任务: 77.电系统-厂务类-GC [2025-11-05 11:14:29] 错误: 点击失败 (GC): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: GC 有点问题 任务 '77.电系统-厂务类-GC' 执行失败 🔁 正在执行任务: 78.电系统-厂务类-water [2025-11-05 11:14:29] 操作: 开始执行任务: 78.电系统-厂务类-water [2025-11-05 11:14:29] 错误: 点击失败 (water): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: water 有点问题 任务 '78.电系统-厂务类-water' 执行失败 🔁 正在执行任务: 79.电系统-厂务类-Elec [2025-11-05 11:14:29] 操作: 开始执行任务: 79.电系统-厂务类-Elec [2025-11-05 11:14:29] 错误: 点击失败 (Elec): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: Elec 有点问题 任务 '79.电系统-厂务类-Elec' 执行失败 🔁 正在执行任务: 80.电系统-厂务类-CFC [2025-11-05 11:14:29] 操作: 开始执行任务: 80.电系统-厂务类-CFC [2025-11-05 11:14:29] 错误: 点击失败 (CFC): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: CFC 有点问题 任务 '80.电系统-厂务类-CFC' 执行失败 🔁 正在执行任务: 81.电系统-大宗气站-大宗气站1 [2025-11-05 11:14:29] 操作: 开始执行任务: 81.电系统-大宗气站-大宗气站1 [2025-11-05 11:14:29] 错误: 点击失败 (大宗气站): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 大宗气站 有点问题 任务 '81.电系统-大宗气站-大宗气站1' 执行失败 🔁 正在执行任务: 82.电系统-大宗气站-大宗气站2 [2025-11-05 11:14:29] 操作: 开始执行任务: 82.电系统-大宗气站-大宗气站2 [2025-11-05 11:14:29] 错误: 点击失败 (大宗气站2): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 大宗气站2 有点问题 任务 '82.电系统-大宗气站-大宗气站2' 执行失败 🔁 正在执行任务: 83.FAB [2025-11-05 11:14:29] 操作: 开始执行任务: 83.FAB [2025-11-05 11:14:29] 错误: 点击失败 (220kV PS1a(按建筑分)): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 220kV PS1a(按建筑分) 有点问题 任务 '83.FAB' 执行失败 🔁 正在执行任务: 84.电系统-220Kv PS1a-CUB [2025-11-05 11:14:29] 操作: 开始执行任务: 84.电系统-220Kv PS1a-CUB [2025-11-05 11:14:29] 错误: 点击失败 (CUB): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: CUB 有点问题 任务 '84.电系统-220Kv PS1a-CUB' 执行失败 🔁 正在执行任务: 85.电系统-220Kv PS1a-WWT [2025-11-05 11:14:29] 操作: 开始执行任务: 85.电系统-220Kv PS1a-WWT [2025-11-05 11:14:29] 错误: 点击失败 (WWT): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: WWT 有点问题 任务 '85.电系统-220Kv PS1a-WWT' 执行失败 🔁 正在执行任务: 86.电系统-220Kv PS1a-OS [2025-11-05 11:14:29] 操作: 开始执行任务: 86.电系统-220Kv PS1a-OS [2025-11-05 11:14:29] 错误: 点击失败 (OS): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: OS 有点问题 任务 '86.电系统-220Kv PS1a-OS' 执行失败 🔁 正在执行任务: 87.电系统-220Kv PS1a-ADB [2025-11-05 11:14:29] 操作: 开始执行任务: 87.电系统-220Kv PS1a-ADB [2025-11-05 11:14:29] 错误: 点击失败 (ADB): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: ADB 有点问题 任务 '87.电系统-220Kv PS1a-ADB' 执行失败 🔁 正在执行任务: 88.电系统-220Kv PS1a-XDH [2025-11-05 11:14:29] 操作: 开始执行任务: 88.电系统-220Kv PS1a-XDH [2025-11-05 11:14:29] 错误: 点击失败 (XDH): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: XDH 有点问题 任务 '88.电系统-220Kv PS1a-XDH' 执行失败 🔁 正在执行任务: 89.电系统-220Kv PS1a-生活区 [2025-11-05 11:14:29] 操作: 开始执行任务: 89.电系统-220Kv PS1a-生活区 [2025-11-05 11:14:29] 错误: 点击失败 (生活区): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 生活区 有点问题 任务 '89.电系统-220Kv PS1a-生活区' 执行失败 🔁 正在执行任务: 90.电系统-220Kv PS1a-未来馆 [2025-11-05 11:14:29] 操作: 开始执行任务: 90.电系统-220Kv PS1a-未来馆 [2025-11-05 11:14:29] 错误: 点击失败 (未来馆): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 未来馆 有点问题 任务 '90.电系统-220Kv PS1a-未来馆' 执行失败 🔁 正在执行任务: 91.电系统-工艺厂务能耗比 [2025-11-05 11:14:29] 操作: 开始执行任务: 91.电系统-工艺厂务能耗比 [2025-11-05 11:14:29] 错误: 点击失败 (工艺厂务能耗比): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 工艺厂务能耗比 有点问题 任务 '91.电系统-工艺厂务能耗比' 执行失败 🔁 正在执行任务: 92.电系统-工艺+厂务耗电量 [2025-11-05 11:14:29] 操作: 开始执行任务: 92.电系统-工艺+厂务耗电量 [2025-11-05 11:14:29] 错误: 点击失败 (工艺+厂务耗电量): 'NoneType' object has no attribute 'find_element' 有点问题 [2025-11-05 11:14:29] 错误: 操作中断于: 工艺+厂务耗电量 有点问题 任务 '92.电系统-工艺+厂务耗电量' 执行失败 🎉 总结:0/24 个任务执行成功 🔚 程序结束 Process finished with exit code 0 什么情况
最新发布
11-06
你遇到的问题非常典型,从日志来看: ``` 'NoneType' object has no attribute 'find_element' ``` 这是 **Selenium 中最常见、最关键的错误之一**: 👉 **`self.driver` 是 `None`,也就是说浏览器没有成功初始化!** --- ## 🔍 错误分析 你的程序执行流程是这样的: ```python login = EnergySystemLogin() driver = login.get_driver() # ❌ 此时 driver == None # 然后传给 MenuNavigator navigator = MenuNavigator(driver, ...) # 传进去的是 None # 所有点击操作都会失败: element = WebDriverWait(self.driver, ...).until(...) # ↑ self.driver 是 None → 报错 'NoneType' object has no attribute 'find_element' ``` ### 🧩 根本原因: > 你调用了 `login.get_driver()`,但从未调用过 `login.initialize_driver()`! 而 `initialize_driver()` 是真正创建 `self.driver` 的地方。 所以 `get_driver()` 返回的是 `None`。 --- ## ✅ 解决方案:必须显式初始化浏览器 你需要在获取 `driver` 之前,先调用 `.initialize_driver()` 并确保它成功。 --- ### ✅ 修改主程序部分(关键修复) 将原来的: ```python login = EnergySystemLogin() driver = login.get_driver() ``` 改成: ```python login = EnergySystemLogin() # 🔥 必须先初始化浏览器 if not login.initialize_driver(): print("❌ 浏览器初始化失败,程序退出") sys.exit(1) driver = login.get_driver() # 这时候才不是 None ``` --- ### ✅ 同时修改 `initialize_driver()` 方法:让它抛出异常或返回 False 更清晰 你现在的方法里写的是: ```python def initialize_driver(self): try: # ... 初始化代码 ... return True except: pass # ❌ 吞掉了所有错误,你看不到哪里出问题了! ``` 这会导致即使 Chrome 启动失败(比如路径不对、驱动不匹配),你也 **完全不知道**。 --- ### ✅ 推荐改法:打印具体错误 + 返回布尔值 ```python def initialize_driver(self): """初始化Chrome浏览器""" try: options = webdriver.ChromeOptions() # --- 反检测设置 --- options.add_argument("--disable-blink-features=AutomationControlled") options.add_argument("--start-maximized") options.add_argument("--headless=new") options.add_argument("--disable-gpu") options.add_argument("--no-sandbox") options.add_argument("--disable-dev-shm-usage") options.add_argument("--window-size=1920,1080") options.add_argument("--log-level=3") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option("useAutomationExtension", False) download_dir = r"D:\Class\能管比对\导出文件" if not os.path.exists(download_dir): os.makedirs(download_dir) prefs = { "download.default_directory": download_dir, "download.prompt_for_download": False, "download.directory_upgrade": True, "safebrowsing.enabled": True, "profile.default_content_settings.popups": 0, "plugins.always_open_pdf_externally": False, } options.add_experimental_option("prefs", prefs) self.driver = webdriver.Chrome(options=options) self.driver.implicitly_wait(10) self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => false});") self.log_action(f"浏览器初始化完成,下载路径: {download_dir}") return True except Exception as e: self.log_error(f"浏览器初始化失败: {str(e)}") return False ``` --- ## 🛠️ 再检查几个潜在问题 ### 1. 是否安装了 `chromedriver`?是否版本匹配? 你用了 `webdriver.Chrome()`,这意味着: - 你的系统 PATH 中必须有 `chromedriver.exe` - 或者你使用了最新方式(推荐):用 `selenium 4.6+` 自动下载 driver ✅ **建议升级到 Selenium 4.6+,然后改用 `Service` 自动管理驱动** #### 示例(推荐写法): ```python from selenium import webdriver from selenium.webdriver.chrome.service import Service # ... def initialize_driver(self): try: options = webdriver.ChromeOptions() options.add_argument("--headless=new") # ... 其他选项 ... service = Service() # 会自动下载并启动合适的 chromedriver self.driver = webdriver.Chrome(service=service, options=options) # ... 后续设置 ... return True except Exception as e: self.log_error(f"驱动启动失败: {e}") return False ``` 这样你就不用手动维护 `chromedriver.exe` 了。 --- ### 2. 无头模式下页面加载慢?元素找不到? 你在用 `--headless=new`,有些网页在无头模式下行为不同,比如: - JS 加载顺序不同 - 某些元素渲染延迟 📌 建议调试时**先关闭无头模式**,确认逻辑正确后再开启。 可以加一个开关: ```python HEADLESS = True # 改成 False 查看页面是否正常加载 # 在 options 中: if HEADLESS: options.add_argument("--headless=new") ``` --- ## ✅ 最终修复总结 | 问题 | 修复方式 | |------|----------| | `driver is None` | 调用 `login.initialize_driver()` 初始化浏览器 | | 错误被吞掉 | `except Exception as e:` 替代 `except: pass` | | 驱动问题 | 使用 `Service()` 让 Selenium 自动管理 `chromedriver` | | 无法定位元素 | 关闭 headless 模式调试,检查 XPath 是否正确 | --- ## ✅ 修改后的主程序片段(重点) ```python if __name__ == "__main__": login = None download_dir = r"D:\Class\能管比对\导出文件" clear_download_dir(download_dir) try: login = EnergySystemLogin() # 🔥 关键:必须初始化浏览器 if not login.initialize_driver(): print("🛑 浏览器初始化失败,程序终止") sys.exit(1) driver = login.get_driver() # 现在 driver 不是 None 了 # 加载操作模块... module_names = ["menu_operations0", "menu_operations4"] ALL_OPERATIONS = {} for mod_name in module_names: try: module = __import__(mod_name) import importlib importlib.reload(module) combined_in_mod = load_all_operations(module) ALL_OPERATIONS.update(combined_in_mod) print(f"📁 已从模块 '{mod_name}' 加载 {len(combined_in_mod)} 项任务\n") except Exception as e: print(f"❌ 加载模块 {mod_name} 失败: {e}") navigator = MenuNavigator(driver, operations_dict=ALL_OPERATIONS) tasks_to_run = list(ALL_OPERATIONS.keys()) print(f"\n📋 共发现 {len(tasks_to_run)} 个待执行任务:") for i, task in enumerate(tasks_to_run, 1): print(f" {i}. {task}") success_count = 0 for task in tasks_to_run: print(f"\n🔁 正在执行任务: {task}") if navigator.navigate(task): success_count += 1 else: print(f"❌ 任务 '{task}' 执行失败") print(f"\n🎉 总结:{success_count}/{len(tasks_to_run)} 个任务执行成功") except KeyboardInterrupt: print("\n\n🛑 用户手动中断程序") except Exception as e: print(f"🚨 程序发生未预期异常: {str(e)}") finally: if login: login.cleanup() print("🔚 程序结束") ``` --- ## ✅ 下一步你应该怎么做? 1. ✅ 添加 `login.initialize_driver()` 2. ✅ 打印初始化失败的具体原因 3. ✅ 调试时关闭 `--headless` 看看页面能不能打开 4. ✅ 检查 `menu_operations0.py` 和 `menu_operations4.py` 中的 XPath 是否正确 5. ✅ 确保登录成功(可以暂时去掉 `--headless` 看是否真登录进去了) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值