
1. 项目概述与核心需求解析最近在几个技术社群里看到不少朋友在讨论一个挺实际的需求如何让电脑在无人值守的情况下自动完成一些网页端的“挂机”任务比如在线学习平台需要累积学习时长或者某些需要保持在线状态的网页应用。手动盯着屏幕显然不现实而市面上的一些“鼠标连点器”或“自动刷新”工具又往往功能单一或者存在安全风险。于是一个结合了Python编程能力和浏览器自动化技术的方案就浮出水面了——使用Python的Selenium库驱动Microsoft Edge浏览器实现自动化操作并解决长时间运行可能遇到的屏幕自动熄灭问题。这个项目的核心就是利用Selenium这个强大的Web自动化测试工具模拟真实用户对Edge浏览器的操作。它不仅仅是简单的页面刷新而是可以模拟点击、输入、滚动、等待等一系列复杂交互让挂机行为更接近真人操作从而降低被目标网站检测为“机器人”的风险。同时为了解决电脑因节能设置而自动锁屏或休眠导致程序中断的问题我们还需要编写一段“防熄屏”代码让系统保持活跃状态。适合谁来参考这篇内容呢如果你是一名有一定Python基础希望将自动化技术应用到实际场景中的开发者或爱好者或者你是一名运维、测试人员想了解如何通过脚本模拟用户行为甚至你只是对“解放双手”的自动化脚本感兴趣想学习一个完整的实战案例那么这篇从环境搭建到代码实现再到避坑技巧的详细指南应该能给你提供一条清晰的路径。整个过程我们将围绕Edge浏览器展开因为它作为Windows系统的“亲儿子”在兼容性和性能上通常有不错的表现。2. 环境准备与工具选型背后的逻辑工欲善其事必先利其器。在开始写代码之前我们需要搭建一个稳定、可复现的自动化环境。这里的工具选型每一步都有其考量盲目安装很容易掉进版本兼容的坑里。2.1 Python环境为什么推荐3.8首先自然是Python。我强烈建议使用Python 3.8或以上的版本。原因有几个一是Selenium 4.x版本对Python 3.7及以下版本的支持已逐步减弱新特性可能无法使用二是Python 3.8在异步IO、字典顺序等方面有重要改进能让我们的脚本运行得更稳定。安装时务必勾选“Add Python to PATH”这是老生常谈但新手必踩的坑。安装完成后在命令行输入python --version确认版本。注意如果你的电脑上同时存在Python 2和Python 3可能需要使用python3和pip3命令。在Windows上可以通过py -3.9这样的命令来指定版本运行。2.2 Selenium库安装与版本锁定策略接下来是核心工具Selenium。通过pip安装非常简单pip install selenium。但这里有个关键技巧强烈建议锁定一个稳定的版本。直接pip install selenium会安装最新版而最新版有时会引入不兼容的改动。对于生产或长期运行的脚本我习惯使用pip install selenium4.10.0这样的命令来安装一个我验证过稳定的版本例如4.10.0。你可以通过pip show selenium查看已安装的版本信息。Selenium的本质是一个通过WebDriver协议与浏览器通信的客户端库。它本身不包含浏览器也不负责驱动浏览器它只是发送指令如“打开页面”、“点击元素”的“指挥官”。2.3 Edge浏览器与WebDriver版本同步的生死线这是整个环境搭建中最容易出错的一环。Selenium需要通过一个名为msedgedriver的驱动程序来操控Edge浏览器。驱动程序的版本必须与Edge浏览器的版本严格匹配否则程序将无法启动。查看Edge浏览器版本打开Edge浏览器点击右上角三个点 - 帮助和反馈 - 关于Microsoft Edge。记下版本号例如115.0.1901.183。下载对应版本的WebDriver官方下载地址是https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/在网站上找到与你的Edge浏览器主版本号一致的驱动进行下载。例如Edge版本是115.1901.183就下载适用于“115”版本的驱动。根据你的系统Win32/64 macOS Linux选择正确的文件。配置WebDriver路径下载后是一个名为msedgedriver.exe的可执行文件。你有三种方式让Python找到它方法一推荐便于管理将msedgedriver.exe放在你的Python项目目录下。方法二系统级配置将其放在一个固定路径如C:\WebDriver\并将该路径添加到系统的PATH环境变量中。方法三代码中指定在Python代码里直接指定驱动文件的绝对路径。这是最明确、最不容易出错的方式我们后续代码会采用这种方式。实操心得我习惯为每个自动化项目单独建一个文件夹里面存放项目代码、日志以及对应的msedgedriver.exe。这样项目隔离性好迁移和版本管理也方便。千万不要把不同版本的驱动混放在系统目录那将是灾难的开始。2.4 集成开发环境IDE选型写Python代码一个好用的IDE能事半功倍。对于这个项目VS Code轻量、插件丰富。需要安装Python扩展和Pylance。配置虚拟环境稍微需要一点步骤但灵活性极高。PyCharm功能强大的专业IDE对Python项目管理和虚拟环境支持开箱即用适合中大型项目。Jupyter Notebook适合做探索性分析和代码片段测试但不适合作为最终自动化脚本的运行环境。我个人更倾向于使用VS Code因为它对Markdown写笔记、JSON配置以及终端操作的支持都很流畅适合这种“脚本文档”类型的项目。3. 核心代码实现与自动化逻辑拆解环境准备好后我们进入核心部分编写自动化脚本。我们的目标是创建一个健壮的、可配置的自动挂机程序。我会将代码分成几个功能模块来讲解并解释每一行关键代码背后的意图。3.1 浏览器启动与基础配置启动浏览器不是简单的一行代码合理的配置可以避免很多奇怪的问题比如被网站检测到自动化工具。from selenium import webdriver from selenium.webdriver.edge.service import Service from selenium.webdriver.edge.options import Options import time import os import pyautogui # 用于防熄屏操作 # 1. 配置Edge浏览器选项 edge_options Options() # 关键配置1启用“实验性选项”来尝试隐藏自动化特征 # 此选项在Selenium 4中推荐使用可以避免一些简单的检测 edge_options.add_experimental_option(excludeSwitches, [enable-automation]) edge_options.add_experimental_option(useAutomationExtension, False) # 关键配置2防止WebDriver特征被暴露 # 一些网站会通过navigator.webdriver属性来检测自动化这个配置可以将其设置为undefined edge_options.add_argument(--disable-blink-featuresAutomationControlled) # 其他实用配置 edge_options.add_argument(--no-sandbox) # 在Linux或某些Docker环境下可能需要 # edge_options.add_argument(--headless) # 无头模式不显示浏览器界面。挂机时通常关闭以便观察。 edge_options.add_argument(--disable-gpu) # 禁用GPU硬件加速有时可增加稳定性 edge_options.add_argument(--window-size1920,1080) # 设置初始窗口大小 # 2. 指定WebDriver路径并创建服务 # 将 your_path_to/msedgedriver.exe 替换为你的实际路径 driver_path os.path.join(os.getcwd(), msedgedriver.exe) service Service(executable_pathdriver_path) # 3. 启动浏览器 driver webdriver.Edge(serviceservice, optionsedge_options) # 4. 执行CDP命令进一步覆盖自动化痕迹Selenium 4语法 driver.execute_cdp_cmd(Page.addScriptToEvaluateOnNewDocument, { source: Object.defineProperty(navigator, webdriver, { get: () undefined }); })代码解读与注意事项Options()对象用于设置浏览器启动时的各种参数。excludeSwitches和useAutomationExtension是经典的隐藏Chrome/Edge顶部“正受到自动测试软件控制”提示的配置。--disable-blink-featuresAutomationControlled是更进一步的隐藏手段。execute_cdp_cmd是直接通过Chrome DevTools Protocol执行命令在页面加载前注入JavaScript将navigator.webdriver属性覆盖掉这是目前应对检测比较有效的方法之一。重要这些隐藏手段并非万能对于反爬机制严密的网站可能依然无效。自动化访问应始终遵守目标网站的robots.txt和服务条款。3.2 模拟用户行为访问、等待与交互挂机不仅仅是打开页面还需要模拟人类的一些随机行为避免行为模式过于规律。# 访问目标网址 target_url https://example.com/learning-platform # 请替换为你的实际网址 driver.get(target_url) print(f已访问: {target_url}) # 强制等待确保页面基本元素加载初学者适用但非最佳 time.sleep(5) # --- 更优方案使用Selenium的“显式等待” --- from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By try: # 等待页面某个关键元素比如登录后的用户头像出现最多等10秒 user_avatar WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, .user-avatar)) ) print(关键元素加载完成页面已就绪。) except Exception as e: print(f等待元素超时或未找到: {e}) # 可以在这里记录日志或进行其他异常处理 # --- 模拟一些用户操作 --- # 示例1随机滚动页面模拟阅读 import random scroll_height driver.execute_script(return document.body.scrollHeight) for _ in range(3): # 随机滚动到页面中部某个位置 scroll_to random.randint(200, int(scroll_height * 0.6)) driver.execute_script(fwindow.scrollTo(0, {scroll_to});) time.sleep(random.uniform(2, 4)) # 随机等待2-4秒 # 示例2随机点击一些无害的链接或按钮确保不会触发重要操作 # 首先找到所有可能是链接或按钮的元素 all_links driver.find_elements(By.TAG_NAME, a) safe_links [link for link in all_links if link.is_displayed() and link.is_enabled()] if safe_links: link_to_click random.choice(safe_links[:5]) # 只在前5个可见链接中随机选 try: link_to_click.click() print(f随机点击了链接当前URL变为: {driver.current_url}) time.sleep(random.uniform(3, 6)) # 点击后可以回退或者继续在新页面操作 driver.back() time.sleep(2) except Exception as e: print(f点击链接时出错: {e})行为模拟的逻辑完全静止的页面访问很容易被识别。加入随机滚动、随机等待时间、随机但安全的点击操作可以极大地增加行为模式的“熵”使其更像一个真实用户在浏览。核心原则是所有操作都应该是“无害”的避免点击“注销”、“删除”、“提交订单”等关键按钮。可以通过CSS选择器精准定位那些装饰性或导航性的元素。3.3 防熄屏机制的实现原理与代码这是项目的另一个核心点。电脑的锁屏和休眠是操作系统级别的电源管理策略仅仅保持浏览器活动不一定能阻止。我们的策略是模拟用户输入欺骗系统认为用户正在操作。def keep_alive(interval60): 防熄屏/防休眠函数。 通过模拟轻微的鼠标移动或按键操作使系统认为用户处于活动状态。 :param interval: 执行操作的间隔时间单位秒。默认60秒一次。 import pyautogui import random import threading def _worker(): while True: try: # 方案1模拟极小的鼠标移动推荐 # 获取当前鼠标位置 current_x, current_y pyautogui.position() # 在当前位置基础上随机偏移1-2个像素 move_x current_x random.choice([-1, 0, 1]) move_y current_y random.choice([-1, 0, 1]) pyautogui.moveTo(move_x, move_y, duration0.1) # 方案2模拟按下一次“Shift”键备用 # pyautogui.press(shift) # 偶尔按一次不要太频繁 print(f[防熄屏] 已执行保活操作于 {time.strftime(%H:%M:%S)}) except Exception as e: print(f[防熄屏] 操作执行出错: {e}) # 等待指定间隔 time.sleep(interval) # 创建一个守护线程这样主程序退出时这个线程也会自动结束 thread threading.Thread(target_worker, daemonTrue) thread.start() print(f防熄屏线程已启动每 {interval} 秒活动一次。) # 在脚本主逻辑开始后启动防熄屏 keep_alive(interval300) # 每5分钟活动一次对于防休眠通常足够原理与注意事项为什么是线程防熄屏需要在一个独立的、循环运行的线程中执行不能阻塞主线程主线程可能在执行网页操作或等待。为什么用pyautogui它直接模拟系统级的输入事件比单纯发送浏览器指令更有效。确保已安装pip install pyautogui。移动像素为什么这么小移动1-2个像素人眼几乎无法察觉不会干扰你正常使用电脑如果你同时在用的话。移动幅度过大反而显得异常。间隔时间设置Windows和macOS的默认锁屏时间通常是几分钟到十几分钟。将间隔设置为300秒5分钟是一个比较安全且保守的值既能有效防止休眠又不会因操作过于频繁而产生不必要的系统负载。守护线程daemon设置为daemonTrue意味着当主程序所有非守护线程结束时这个保活线程会自动退出避免程序无法正常关闭。重要警告请谨慎使用此功能并确保你了解其影响。在不需要时应及时关闭脚本。切勿用于任何违反计算机使用规定或绕过合法系统限制的场景。3.4 完整的挂机循环与异常处理将以上模块组合起来形成一个可持续运行、具备一定容错能力的挂机循环。def main_hanging_session(duration_hours2): 主挂机会话 :param duration_hours: 计划挂机的总时长小时 start_time time.time() end_time start_time (duration_hours * 3600) cycle_count 0 while time.time() end_time: cycle_count 1 print(f\n--- 开始第 {cycle_count} 个挂机周期 ---) try: # 1. 确保浏览器窗口在最前可选 # driver.minimize_window() # time.sleep(1) # driver.maximize_window() # 2. 刷新页面模拟用户重新访问或保持会话 driver.refresh() print(页面已刷新。) # 使用显式等待等待某个元素出现 WebDriverWait(driver, 15).until( EC.presence_of_element_located((By.TAG_NAME, body)) ) # 3. 执行一系列模拟用户行为 simulate_user_activity(driver) # 4. 计算并等待下一个周期随机化等待时间 # 基础等待时间 随机扰动例如每10-15分钟一个周期 base_wait 10 * 60 # 10分钟 random_wait random.randint(-120, 180) # -2到3分钟的随机扰动 next_wait max(60, base_wait random_wait) # 确保至少等待1分钟 print(f本轮活动结束。等待 {next_wait//60} 分 {next_wait%60} 秒后开始下一轮。) time.sleep(next_wait) except KeyboardInterrupt: print(\n检测到用户中断CtrlC准备退出...) break except Exception as e: print(f挂机周期中出现未预期错误: {e}) # 记录错误到日志文件 with open(hang_error.log, a) as f: f.write(f{time.ctime()}: {e}\n) # 尝试重启浏览器简易版先退出再启动 print(尝试恢复浏览器会话...) try: driver.quit() except: pass time.sleep(5) # 重新初始化driver (这里需要重新执行之前的初始化代码为简洁起见可以封装为一个函数) # driver init_browser() # 如果重启失败则退出循环 print(恢复失败程序退出。) break print(f\n挂机任务结束。总共运行了 {cycle_count} 个周期。) driver.quit() def simulate_user_activity(driver): 封装模拟用户活动的函数 # 随机滚动 scroll_actions random.randint(1, 3) for _ in range(scroll_actions): scroll_pixel random.randint(100, 500) driver.execute_script(fwindow.scrollBy(0, {scroll_pixel});) time.sleep(random.uniform(1.0, 2.5)) # 随机寻找并点击无害元素例如页码、标签页、展开按钮 # 使用更精准的选择器避免误点 harmless_selectors [ a.pagination-link, button[aria-label更多], .tab-item, div.collapsible-header, span.icon-expand ] for selector in harmless_selectors: if random.random() 0.7: # 30%的概率执行该选择器的查找点击 try: elements driver.find_elements(By.CSS_SELECTOR, selector) if elements: elem random.choice(elements) if elem.is_displayed() and elem.is_enabled(): elem.click() time.sleep(random.uniform(2, 4)) print(f模拟点击了: {selector}) break # 点击一次后即可退出 except: continue # 程序入口 if __name__ __main__: # 初始化浏览器 # driver webdriver.Edge(serviceservice, optionsedge_options) # 这里需要用到前面定义的service和options # 启动防熄屏 keep_alive(interval300) # 开始挂机 main_hanging_session(duration_hours2)4. 高级技巧、常见问题与排查实录即使代码写好了在实际运行中你肯定会遇到各种各样的问题。下面是我在多次实践中总结出来的“避坑指南”和问题排查思路。4.1 如何应对网站的反爬/反自动化检测简单的隐藏自动化特征如3.1节所述可能不足以应对更高级的检测。网站可能会通过以下方式检测WebDriver属性我们已经通过CDP命令覆盖了navigator.webdriver。浏览器指纹检查插件列表、语言、屏幕分辨率、时区等是否与正常浏览器一致。行为模式鼠标移动轨迹、点击速度、输入速度是否过于“机械”或“匀速”。Cookie和本地存储自动化浏览器可能缺少正常的登录态或历史记录。应对策略使用更真实的User-Agent有些自动化驱动会有特定的UA。可以手动设置一个常见的普通浏览器UA。edge_options.add_argument(user-agentMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183)引入随机延迟在所有操作前后加入time.sleep(random.uniform(a, b))让等待时间不均匀。模拟人类鼠标移动轨迹pyautogui的移动是直线瞬移。更高级的模拟可以使用pyautogui.moveTo(x, y, durationt)其中duration参数让移动有耗时或者使用更复杂的库生成贝塞尔曲线轨迹。使用浏览器配置文件让Selenium加载一个已登录的、有正常浏览历史的用户数据目录这样浏览器指纹会更真实。# 注意需要先手动用Edge登录目标网站并找到其用户数据路径 # user_data_dir rC:\Users\YourName\AppData\Local\Microsoft\Edge\User Data\Default # edge_options.add_argument(fuser-data-dir{user_data_dir})警告此方法有隐私和安全风险且Edge可能禁止多实例同时访问同一数据目录需谨慎使用。4.2 WebDriver版本不匹配或失效这是最高频的错误。症状通常是WebDriverException: Message: unknown error: cannot find Edge binary或SessionNotCreatedException。排查步骤核对版本再次确认Edge浏览器版本和下载的msedgedriver版本号的主版本是否一致。检查路径确认代码中executable_path指向的路径是否正确文件名是否拼写错误。Edge自动更新Edge浏览器会自动更新。如果某天脚本突然不能用了第一反应就是检查Edge是否升级了然后去下载新版本的驱动。驱动权限在Linux/macOS系统下需要给msedgedriver添加可执行权限chmod x msedgedriver。4.3 元素定位失败StaleElementReferenceException在页面刷新或AJAX动态加载后之前找到的元素引用会“过期”再次操作就会抛出此异常。解决方案重新查找元素在try...except块中捕获这个异常然后在异常处理中重新使用find_element定位一次。使用更稳定的定位策略优先使用ID、name其次是CSS Selector或XPath。避免使用可能随内容变化的文本或索引位置。使用POMPage Object Model模式对于复杂的项目将页面元素定位和操作封装成类每次操作前重新获取元素可以有效管理元素生命周期。4.4 脚本在后台运行时被系统中断即使有防熄屏代码Windows的“睡眠”设置仍然可能中断所有程序。系统级设置检查进入控制面板 - 电源选项 - 更改计划设置 - 更改高级电源设置。找到“睡眠”选项将“经过此时间后睡眠”设置为“从不”。找到“硬盘”选项将“经过此时间后关闭硬盘”也设置为“从不”或一个很长的时间。对于笔记本电脑注意区分“接通电源”和“使用电池”两种模式都要进行设置。4.5 日志记录与监控一个健壮的自动化脚本必须有日志。import logging # 配置日志 logging.basicConfig( levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[ logging.FileHandler(auto_hang.log, encodingutf-8), logging.StreamHandler() # 同时输出到控制台 ] ) logger logging.getLogger(__name__) # 在代码中使用logger代替print logger.info(已访问: %s, target_url) try: # some operation pass except Exception as e: logger.error(操作失败错误信息: %s, e, exc_infoTrue) # exc_infoTrue会打印堆栈跟踪良好的日志可以帮助你在脚本长时间运行后回溯发生了什么尤其是当它半夜因为未知错误停止时。4.6 资源管理与优雅退出脚本可能运行数小时需要管理好资源。内存泄漏虽然Selenium会管理大部分资源但长时间运行后如果反复创建driver而不quit()可能导致内存占用上升。确保异常处理中有driver.quit()。优雅退出使用try...finally块确保无论是否出错最后都能关闭浏览器。try: # 主逻辑 main_hanging_session() except KeyboardInterrupt: logger.info(用户手动终止程序。) except Exception as e: logger.exception(程序发生未捕获异常: ) finally: if driver in locals(): driver.quit() logger.info(浏览器驱动已关闭。) print(程序退出。)5. 项目扩展思路与优化建议一个基础的自动挂机脚本完成后你可以根据实际需求将其扩展得更加强大和智能。5.1 多账号与多任务管理如果需要同时为多个账号挂机或者在不同网站执行任务可以考虑使用多线程或异步IO为每个账号/任务启动一个独立的线程或异步任务。注意每个线程需要独立的webdriver.Edge实例和用户数据目录避免会话混淆。队列化管理将任务如URL、操作步骤放入队列由一组工作线程消费执行。配置文件驱动将账号信息、目标URL、操作步骤等写入JSON或YAML配置文件脚本读取配置执行提高可维护性。5.2 集成任务调度与通知定时启动结合Windows任务计划程序Task Scheduler或Linux的Cron让脚本在指定时间自动运行。状态监控与通知使用邮件smtplib、钉钉/企业微信机器人、Telegram Bot等在脚本启动、完成、出错时发送通知。例如用requests库调用一个Webhook。5.3 增加容错与自愈能力网络异常重试在访问网页或查找元素时加入重试机制如使用tenacity库。心跳检测定期检查浏览器窗口是否还存在页面是否处于预期状态如登录态是否保持。如果发现异常自动执行恢复流程如重新登录。OCR辅助对于有验证码的网站虽然本项目初衷是避开可以集成OCR库如ddddocr、pytesseract进行简单识别但复杂验证码仍需人工或更高级方案。5.4 性能与隐身优化禁用图片和CSS如果页面加载速度是瓶颈可以添加参数加速。prefs {profile.managed_default_content_settings.images: 2} # 2为禁用 edge_options.add_experimental_option(prefs, prefs)使用代理IP如果需要可以在Options中配置代理服务器但务必遵守法律法规和网站规定。指纹混淆研究并使用像undetected-chromedriver这样的第三方库它专门用于绕过自动化检测但请注意其可能违反某些网站的服务条款。最后我必须再次强调自动化脚本的使用伦理。这个技术本身是中立的但请务必将其用于合法的、符合目标网站服务条款的场景。用于学习、测试或者完成那些允许自动化的重复性工作是完全没问题的。尊重网站服务器的负载在随机等待时间上设置得宽松一些避免过于频繁的请求。技术是为了提高效率而不是制造麻烦。在实际操作中从简单的页面开始测试逐步增加复杂性耐心调试你就能打造出一个稳定可靠的自动化助手。