
1. 项目概述为什么Selenium需要性能调优如果你用过Selenium做自动化测试或者数据抓取大概率经历过这样的场景脚本跑得慢吞吞页面加载等半天一个简单的流程要好几分钟才能走完。尤其是在处理动态加载、复杂交互或者需要大量数据验证的页面时那种等待的焦灼感简直让人想把电脑砸了。这背后往往不是你的代码逻辑有问题而是Selenium的默认配置在“偷懒”。“Selenium性能提升必备配置”这个主题正是为了解决这个痛点。它不是一个高深莫测的理论研究而是一套从实战中总结出来的、立竿见影的“组合拳”。核心目标很简单在保证脚本稳定性和功能正确性的前提下尽可能地缩短执行时间提升资源利用效率。这不仅仅是快几秒钟的问题对于需要高频次执行的回归测试套件、大规模数据采集任务或者是在CI/CD流水线中集成的自动化测试来说性能提升意味着更快的反馈周期、更低的服务器成本和更高的工作效率。适合谁来关注这些配置无论你是刚入门Selenium、苦于脚本运行太慢的新手还是已经搭建了自动化框架、希望进一步优化执行效率的资深工程师这里面的技巧都能给你带来直接的收益。接下来我不会空谈理论而是会结合我踩过的无数个坑带你逐一拆解那些能让Selenium“飞起来”的关键配置项从浏览器驱动选项到等待策略从网络模拟到资源管理让你彻底告别漫长的等待。2. 核心思路性能瓶颈分析与优化方向在动手改配置之前我们得先搞清楚Selenium脚本到底慢在哪里。盲目优化就像蒙着眼睛跑步可能方向都错了。根据我的经验Selenium的性能瓶颈主要集中在这几个方面2.1 网络与页面加载延迟这是最直观的慢。每次driver.get(url)浏览器都需要发起HTTP请求、接收响应、下载HTML、CSS、JavaScript、图片等资源然后进行解析、渲染。网络波动、服务器响应慢、页面资源过大尤其是未压缩的图片和脚本都会导致这里卡住。更头疼的是单页应用SPA它们往往依赖Ajax动态加载数据页面“看起来”加载完了但你需要的数据可能还在路上。2.2 浏览器自身的开销与渲染Selenium通过WebDriver协议控制的是一个真实的、完整的浏览器实例如Chrome、Firefox。浏览器启动需要时间每个标签页、扩展程序都会消耗内存和CPU。浏览器的渲染引擎如Blink、Gecko在绘制复杂页面时也非常吃资源。默认情况下浏览器会为了更好的用户体验做很多事比如预加载、缓存、GPU加速等但在自动化场景下有些功能非但无益反而成了负担。2.3 脚本逻辑与元素定位效率你的代码本身也可能是瓶颈。低效的元素定位策略如频繁使用XPath遍历复杂DOM、不必要的重复操作、缺乏合理的等待机制滥用time.sleep都会让脚本无谓地空转。此外如果脚本结构混乱没有做好错误处理和重试一次偶然的元素查找失败就可能导致整个脚本长时间挂起。2.4 资源竞争与环境限制当你在同一台机器上并行运行多个Selenium实例时它们会竞争CPU、内存和网络带宽。如果资源不足每个实例都会变慢。此外运行脚本的机器性能、操作系统调度策略也会产生影响。基于以上分析我们的优化思路就清晰了主要围绕四个方向展开削减冗余关闭浏览器非必要的功能阻止不需要的资源加载让浏览器“轻装上阵”。加速交互优化元素定位策略采用智能等待减少脚本“发呆”的时间。改善环境调整浏览器和WebDriver的启动参数合理管理资源。并行与复用在可能的情况下利用并行执行或复用浏览器会话来提升整体吞吐量。接下来的章节我们将深入每个方向给出具体的、可操作的配置方案和代码示例。3. 浏览器启动配置给浏览器“减肥”这是性能提升最有效、最直接的一步。我们通过给浏览器启动时传递特定的Options参数来关闭那些在自动化测试中不需要的功能从而大幅减少内存占用、加速启动和页面加载。3.1 基础性能优化选项以最常用的Chrome浏览器为例我们通过ChromeOptions来配置。以下是一组经过实战检验的“瘦身”配置from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options Options() # 1. 无头模式不显示GUI极大节省资源适用于服务器/后台执行 chrome_options.add_argument(--headless) # 2. 禁用GPU加速在无头模式或某些虚拟环境中GPU加速可能引发问题且无用 chrome_options.add_argument(--disable-gpu) # 3. 禁用浏览器扩展和自动化提示 chrome_options.add_argument(--disable-extensions) chrome_options.add_argument(--disable-blink-featuresAutomationControlled) # 4. 禁用沙箱在某些Docker或CI环境如GitLab Runner中可能需要但会降低安全性仅限可信环境使用。 # chrome_options.add_argument(--no-sandbox) # chrome_options.add_argument(--disable-dev-shm-usage) # 解决/dev/shm内存不足问题 # 5. 设置语言和区域避免因本地化问题导致的意外等待或布局差异 chrome_options.add_argument(--langen-US) chrome_options.add_argument(--window-size1920,1080) # 设置初始窗口大小 driver webdriver.Chrome(optionschrome_options)注意--no-sandbox和--disable-dev-shm-usage是解决Linux环境下常见崩溃问题的方案但它们降低了浏览器的安全隔离级别。请仅在完全可控的测试环境如专用的Docker容器中使用切勿在生产或个人日常使用的浏览器上开启。3.2 实验性选项与高级参数Chrome还提供了一些需要通过add_experimental_option来设置的选项它们能带来更进一步的性能提升。prefs { # 1. 禁止加载图片对于不依赖UI视觉验证的测试此条效果拔群 profile.managed_default_content_settings.images: 2, # 2. 禁止加载CSS在某些场景下也可禁用但可能影响页面布局和JS执行慎用。 # profile.managed_default_content_settings.stylesheets: 2, # 3. 禁止加载Flash现在基本用不到了。 profile.managed_default_content_settings.plugins: 2, # 4. 禁止弹窗如alert, confirm避免脚本被阻塞。 profile.managed_default_content_settings.popups: 2, # 5. 禁用JavaScript仅在你操作的页面完全不依赖JS时使用绝大多数现代网页都需要JS。 # profile.managed_default_content_settings.javascript: 2, # 6. 开启自动下载并设置下载路径避免下载弹窗阻塞。 download.default_directory: /tmp/downloads, download.prompt_for_download: False, download.directory_upgrade: True, safebrowsing.enabled: True # 安全浏览可根据需要关闭 } chrome_options.add_experimental_option(prefs, prefs) # 另一个重要的实验性选项排除Switches chrome_options.add_experimental_option(excludeSwitches, [enable-automation, enable-logging]) # enable-automation 用于隐藏“正受到自动测试软件控制”的提示可能绕过一些简单的反爬。 # enable-logging 禁用DevTools日志输出减少控制台噪音和少量IO开销。3.3 实战心得与避坑指南无头模式不是万能的虽然--headless省资源但有些网站的JavaScript行为在无头模式下和普通模式不同可能导致元素找不到或交互失败。如果你的脚本在无头模式下出错可以先在GUI模式下运行排查。图片加载的取舍禁用图片(images:2)是提升速度的利器尤其对于数据抓取脚本。但对于需要截图对比、验证UI样式的测试则不能禁用。关于disable-blink-featuresAutomationControlled这个参数可以隐藏WebDriver的一些特征对于绕过一些基础的反爬机制有一定效果但它不是银弹。更复杂的反爬需要结合其他策略如修改navigator.webdriver属性。内存管理如果你需要长时间运行脚本或并行多个实例密切关注内存使用情况。除了禁用不必要的功能定期重启浏览器实例driver.quit()- 重新初始化也是一个简单粗暴但有效的防止内存泄漏的方法。4. 网络层优化拦截与模拟浏览器加载的许多资源如广告、跟踪器、非核心CSS/JS、大图对于自动化任务来说是完全无用的。阻止这些资源的加载能直接减少网络请求数和数据传输量显著提升页面加载速度。这需要通过DevTools Protocol来实现。4.1 启用性能日志与网络拦截Selenium可以通过driver.execute_cdp_cmd调用Chrome DevTools Protocol命令。我们主要利用Network域。from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.common.desired_capabilities import DesiredCapabilities # 关键步骤启用性能日志才能捕获网络请求事件 caps DesiredCapabilities.CHROME caps[goog:loggingPrefs] {performance: ALL} chrome_options Options() # ... 其他配置 ... driver webdriver.Chrome(desired_capabilitiescaps, optionschrome_options) # 启用网络跟踪 driver.execute_cdp_cmd(Network.enable, {}) # 设置请求拦截规则阻止特定类型资源 patterns [ {urlPattern: *.jpg*, resourceType: Image, interceptionStage: HeadersReceived}, {urlPattern: *.png*, resourceType: Image, interceptionStage: HeadersReceived}, {urlPattern: *.gif*, resourceType: Image, interceptionStage: HeadersReceived}, {urlPattern: *.css*, resourceType: Stylesheet, interceptionStage: HeadersReceived}, {urlPattern: *ads*, resourceType: Other, interceptionStage: Request}, {urlPattern: *analytics*, resourceType: XHR, interceptionStage: Request}, ] driver.execute_cdp_cmd(Network.setRequestInterception, {patterns: patterns}) # 定义请求事件监听器需配合事件循环处理此处为原理展示 # 实际应用中你需要在一个循环中处理 driver.get_log(performance) 返回的日志 # 解析出网络请求事件并根据URL或资源类型决定是继续加载还是阻塞。 # 由于实现较为复杂通常结合第三方库如 selenium-wire 或直接使用 requests BeautifulSoup 对简单页面进行静态分析更高效。4.2 使用selenium-wire进行更便捷的拦截selenium-wire是一个第三方库它扩展了Selenium让你能非常方便地访问请求和响应。pip install selenium-wirefrom seleniumwire import webdriver chrome_options webdriver.ChromeOptions() chrome_options.add_argument(--headless) # 定义请求拦截函数 def interceptor(request): # 阻止所有图片请求 if request.path.endswith((.png, .jpg, .jpeg, .gif)): request.abort() # 可以修改请求头例如设置User-Agent # request.headers[User-Agent] My Custom User Agent driver webdriver.Chrome(optionschrome_options) # 设置请求拦截器 driver.request_interceptor interceptor driver.get(https://example.com) # 此时页面上的图片将不会被加载 # 你还可以查看所有请求 for request in driver.requests: if request.response: print(request.url, request.response.status_code)4.3 模拟弱网环境性能优化也包括确保脚本在恶劣网络下的稳定性。我们可以模拟不同的网络条件。# 继续使用 selenium-wire 的示例 from seleniumwire import webdriver driver webdriver.Chrome() # 模拟3G快速网络 driver.set_network_conditions( offlineFalse, latency150, # 延迟单位毫秒 download_throughput750 * 1024, # 下载带宽单位比特/秒 (750 kbps) upload_throughput250 * 1024, # 上传带宽单位比特/秒 (250 kbps) ) driver.get(https://example.com) # 页面加载将受到设定的网络条件限制实操心得网络拦截功能强大但要谨慎使用。粗暴地拦截所有CSS或JS很可能导致页面功能失常或布局错乱。最佳实践是先用浏览器开发者工具的“Network”面板分析目标页面识别出哪些是核心资源如主要的app.js、api接口哪些是可有可无的如广告脚本、统计代码、装饰性图片然后有针对性地进行拦截。对于数据抓取拦截图片和字体通常是安全的对于Web功能测试则可能只拦截广告和跟踪器。5. 等待策略优化告别傻等拥抱智能等待滥用time.sleep()是Selenium脚本性能低下的头号杀手。它让脚本无条件等待固定时间无论页面是否早已就绪。正确的做法是使用Selenium提供的显式等待Explicit Wait和隐式等待Implicit Wait。5.1 显式等待精准打击显式等待是针对某个特定条件如元素可见、可点击、元素存在等进行等待条件满足则立即继续超时则抛出异常。这是最推荐的方式。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 driver webdriver.Chrome() driver.get(https://example.com) # 创建一个WebDriverWait对象设置最大等待时间为10秒轮询间隔默认0.5秒 wait WebDriverWait(driver, 10) try: # 等待id为“myElement”的元素出现在DOM中并可见 element wait.until(EC.visibility_of_element_located((By.ID, myElement))) # 等待元素可被点击 clickable_element wait.until(EC.element_to_be_clickable((By.CLASS_NAME, submit-btn))) # 等待旧元素从DOM中消失例如等待加载动画结束 wait.until(EC.invisibility_of_element_located((By.ID, loading-spinner))) # 等待页面标题包含特定文字 wait.until(EC.title_contains(Dashboard)) # 找到元素后进行操作 element.click() clickable_element.send_keys(data) except TimeoutException: print(等待元素超时) # 这里可以加入截图、日志记录等调试操作 driver.save_screenshot(timeout.png)5.2 隐式等待全局守则隐式等待告诉WebDriver在查找任何元素时如果未能立即找到可以轮询DOM一段时间。它设置一次对整个driver生命周期有效。driver.implicitly_wait(10) # 单位秒 # 之后所有的 find_element 操作都会最多等待10秒 element driver.find_element(By.ID, someId)重要警告不要混合使用显式等待和隐式等待混合使用会导致不可预知的等待时间例如显式等待10秒 隐式等待10秒 最多等待20秒。我的建议是永远只使用显式等待因为它更精确、意图更清晰。将driver.implicitly_wait(0)来禁用隐式等待。5.3 自定义等待条件内置的expected_conditions可能不够用你可以轻松自定义。from selenium.webdriver.support.ui import WebDriverWait # 自定义条件等待元素包含特定的文本 def text_to_be_present_in_element(locator, text): def _predicate(driver): try: element_text driver.find_element(*locator).text return text in element_text except Exception: return False return _predicate # 使用自定义条件 wait WebDriverWait(driver, 10) locator (By.CLASS_NAME, status) wait.until(text_to_be_present_in_element(locator, 完成)) # 自定义条件等待某个JavaScript变量被定义或为特定值 def js_variable_equals(variable_name, expected_value): def _predicate(driver): actual_value driver.execute_script(freturn {variable_name};) return actual_value expected_value return _predicate wait.until(js_variable_equals(window.pageLoaded, true))5.4 针对单页应用SPA的等待技巧SPA页面内容动态变化传统的等待页面加载完成EC.presence_of_element_located可能不适用。一个更可靠的方法是等待某个标志性的、代表页面“就绪”的元素出现或者等待网络请求空闲。# 方法1等待某个SPA特有的加载完成标识需要前端配合或观察得出 wait.until(EC.invisibility_of_element_located((By.CSS_SELECTOR, .global-loading))) # 方法2结合 selenium-wire等待特定API请求完成更精准 from seleniumwire import webdriver driver webdriver.Chrome() def wait_for_api_response(api_url_pattern, timeout30): 等待包含特定模式的URL的请求完成并返回响应 import time start_time time.time() while time.time() - start_time timeout: for request in driver.requests: if api_url_pattern in request.url and request.response: # 可以进一步检查 response.status_code 或 body if request.response.status_code 200: return request.response time.sleep(0.5) # 短暂轮询 raise TimeoutError(f等待API {api_url_pattern} 响应超时) driver.get(https://spa-app.com) # 假设点击按钮会触发一个获取用户数据的API driver.find_element(By.ID, load-user).click() response wait_for_api_response(/api/user/profile) # 拿到响应后再继续后续操作比如验证页面数据更新6. 元素定位与操作效率低效的元素定位是脚本内部的性能瓶颈。DOM操作是相对昂贵的尤其是在复杂的页面上。6.1 选择高效的定位器定位器的性能大致排序如下从最快到最慢ID(By.ID): 浏览器原生支持速度极快。Name(By.NAME): 也较快。CSS Selector(By.CSS_SELECTOR): 现代浏览器优化得很好速度很快且非常灵活。XPath(By.XPATH): 功能最强大但通常速度最慢尤其是在复杂的DOM树上。尽量避免使用以//开头的、遍历整个文档的XPath。优化示例# 慢XPath遍历 slow_element driver.find_element(By.XPATH, //div[classcontainer]//ul/li[3]/a) # 快优先使用ID fast_element1 driver.find_element(By.ID, submit-button) # 快使用简洁的CSS Selector fast_element2 driver.find_element(By.CSS_SELECTOR, .container ul li:nth-child(3) a) # 更快如果元素有唯一的类名或属性 fast_element3 driver.find_element(By.CSS_SELECTOR, [data-testiduser-menu])6.2 批量查找与缓存如果需要操作多个同类元素使用find_elements复数一次获取避免循环内重复查找。# 低效每次循环都查找 for i in range(10): # 假设每次都要重新查找这个列表 items driver.find_elements(By.CLASS_NAME, list-item) # ... 操作 items[i] ... # 高效一次查找缓存结果 all_items driver.find_elements(By.CLASS_NAME, list-item) for item in all_items: # ... 操作 item ...对于在脚本中需要多次使用的元素可以将其存储到变量中缓存。但要注意如果页面发生了动态更新如AJAX缓存的元素引用可能会失效StaleElementReferenceException。对于静态部分可以缓存动态部分则需在每次操作前重新查找或使用显式等待。6.3 使用相对定位和链式调用有时相对于一个已找到的稳定元素去定位其子元素比使用绝对路径更可靠和高效。# 先找到一个稳定的父容器 sidebar wait.until(EC.presence_of_element_located((By.ID, sidebar))) # 在父容器范围内查找子元素缩小搜索范围 menu_item sidebar.find_element(By.LINK_TEXT, Settings) # 或者使用相对XPath在父元素上使用. # menu_item sidebar.find_element(By.XPATH, .//a[text()Settings])6.4 JavaScript直接执行对于极其复杂的操作或Selenium原生API效率低下的场景可以考虑直接执行JavaScript。# 示例1滚动到元素可见比Selenium的ActionChains在某些场景下更直接 element driver.find_element(By.ID, target-element) driver.execute_script(arguments[0].scrollIntoView(true);, element) # 示例2一次性设置多个输入框的值避免多次send_keys的模拟键盘事件 script document.getElementById(field1).value value1; document.getElementById(field2).value value2; document.querySelector(.field3).value value3; driver.execute_script(script) # 示例3获取大量数据比通过Selenium逐个获取text属性快 data_script return Array.from(document.querySelectorAll(.data-row)).map(row ({ name: row.querySelector(.name).innerText, value: row.querySelector(.value).innerText })); large_data_set driver.execute_script(data_script)注意事项虽然execute_script很快但它绕过了WebDriver的常规交互模拟可能无法触发一些由原生事件如click,input监听器绑定的行为。使用后需验证页面状态是否符合预期。通常用于只读操作、滚动或批量初始化数据。7. 会话管理与并行执行当测试套件规模变大或者需要处理大量独立任务时如何管理浏览器会话就变得至关重要。7.1 复用浏览器会话高级技巧对于需要登录状态保持的系列操作可以尝试复用浏览器会话避免每次get都重新登录。但这需要处理cookies和本地存储。import pickle import os def save_cookies(driver, path): with open(path, wb) as file: pickle.dump(driver.get_cookies(), file) def load_cookies(driver, path, url): driver.get(url) # 先访问域名才能设置该域名的cookie with open(path, rb) as file: cookies pickle.load(file) for cookie in cookies: # 有些cookie可能有‘expiry’字段需要是整数 if expiry in cookie: # 处理可能的浮点数类型 cookie[expiry] int(cookie[expiry]) try: driver.add_cookie(cookie) except Exception as e: print(f添加cookie失败: {cookie.get(name)}, 错误: {e}) driver.refresh() # 刷新页面使cookie生效 # 使用示例 driver webdriver.Chrome() login_url https://example.com/login driver.get(login_url) # ... 执行登录操作 ... save_cookies(driver, ./cookies.pkl) driver.quit() # 下次启动直接加载cookies访问受保护页面 driver2 webdriver.Chrome() target_url https://example.com/dashboard load_cookies(driver2, ./cookies.pkl, target_url) # 此时应该已处于登录状态7.2 使用webdriver-manager管理驱动手动下载和匹配浏览器与WebDriver版本很麻烦。webdriver-manager可以自动处理。pip install webdriver-managerfrom selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager from webdriver_manager.firefox import GeckoDriverManager # Chrome 示例 service Service(ChromeDriverManager().install()) driver webdriver.Chrome(serviceservice) # Firefox 示例 # service Service(GeckoDriverManager().install()) # driver webdriver.Firefox(serviceservice)7.3 并行执行与资源池对于完全独立的测试用例或抓取任务并行化是提升整体效率的根本方法。可以使用concurrent.futures或多进程库。from concurrent.futures import ThreadPoolExecutor, as_completed from selenium import webdriver from selenium.webdriver.chrome.options import Options def run_test(url): 一个独立的任务函数 chrome_options Options() chrome_options.add_argument(--headless) # ... 其他配置 ... driver webdriver.Chrome(optionschrome_options) try: driver.get(url) # ... 执行具体的测试或抓取逻辑 ... result fSuccess: {url} except Exception as e: result fFailed: {url}, Error: {e} finally: driver.quit() return result urls [https://site1.com, https://site2.com, https://site3.com] # 使用线程池注意WebDriver不是线程安全的每个线程必须有自己的driver实例 max_workers 3 # 根据你的CPU核心数和内存合理设置 with ThreadPoolExecutor(max_workersmax_workers) as executor: future_to_url {executor.submit(run_test, url): url for url in urls} for future in as_completed(future_to_url): url future_to_url[future] try: data future.result() print(data) except Exception as exc: print(f{url} generated an exception: {exc})并行执行的坑资源竞争并行数过多会耗尽内存/CPU导致所有任务都变慢甚至崩溃。需要根据机器性能仔细调整max_workers。线程安全Selenium WebDriver实例不能在线程间共享。必须确保每个线程创建自己独立的driver实例。端口冲突如果并行启动大量Chrome实例可能会遇到端口耗尽的错误。可以通过--remote-debugging-port指定不同端口但管理起来复杂。更常见的做法是使用Selenium Grid或Docker容器来隔离环境。8. 实战问题排查与性能监控即使配置得当脚本仍可能遇到性能问题。掌握排查方法至关重要。8.1 性能瓶颈定位工具浏览器开发者工具 - Performance面板录制脚本执行过程分析加载、脚本执行、渲染等各阶段耗时。浏览器开发者工具 - Network面板查看每个请求的耗时、排队时间找出慢请求。自定义计时在代码关键节点插入时间戳。import time from contextlib import contextmanager contextmanager def timer(description): start time.perf_counter() yield elapsed time.perf_counter() - start print(f{description} took {elapsed:.2f} seconds) with timer(打开首页): driver.get(https://example.com) with timer(查找并点击登录按钮): login_btn wait.until(EC.element_to_be_clickable((By.ID, login))) login_btn.click()8.2 常见性能问题速查表问题现象可能原因排查与解决思路页面加载极慢网络差、页面资源过多、有阻塞渲染的JS/CSS1. 使用Network面板分析请求瀑布图。2. 启用网络拦截阻止非核心资源如图片、广告、分析脚本。3. 检查是否有同步的、外部的JS/CSS文件阻塞。find_element超时元素定位器效率低、页面未加载完成、元素在iframe内1. 优化定位器优先用ID、CSS Selector。2. 在操作前添加合适的显式等待如visibility_of_element_located。3. 检查元素是否在iframe里需要先driver.switch_to.frame。脚本执行慢但网络正常循环内重复查找DOM、使用了慢速XPath、time.sleep滥用1. 缓存重复使用的元素。2. 将find_elements移出循环。3. 将所有time.sleep替换为显式等待。4. 对批量操作考虑使用execute_script。内存使用持续增长浏览器内存泄漏、未正确关闭driver、打开了过多标签页1. 确保每个测试用例或任务结束后调用driver.quit()而不是close()。2. 限制并行实例数量。3. 定期如每运行100个用例重启测试运行器。并行时整体变慢资源CPU、内存、网络带宽竞争1. 降低并行工作线程数(max_workers)。2. 监控系统资源使用情况如用htop,nvidia-smi。3. 考虑使用分布式执行如Selenium Grid。无头模式下元素找不到页面JS在无头模式下行为不同、视口大小影响布局1. 尝试在GUI模式下运行看是否成功。2. 为无头模式设置明确的窗口大小--window-size。3. 添加--user-agent模拟真实浏览器。8.3 日志与截图辅助排查当脚本失败时保存详细的日志和页面截图能极大帮助定位问题。import logging from datetime import datetime # 配置日志 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s, handlers[logging.FileHandler(selenium_perf.log), logging.StreamHandler()]) logger logging.getLogger(__name__) def take_screenshot_and_log(driver, context): 在关键步骤或失败时截图并记录 timestamp datetime.now().strftime(%Y%m%d_%H%M%S) filename fscreenshot_{context}_{timestamp}.png try: driver.save_screenshot(filename) logger.info(f截图已保存: {filename}) # 也可以记录页面源代码谨慎可能很大 # with open(fpage_source_{timestamp}.html, w, encodingutf-8) as f: # f.write(driver.page_source) except Exception as e: logger.error(f截图失败: {e}) # 在可能出错的地方调用 try: element.click() except Exception as e: logger.error(f点击元素失败: {e}) take_screenshot_and_log(driver, click_failed) raise性能调优是一个持续的过程没有一劳永逸的“最佳配置”。最有效的方法是结合监控、 profiling 和迭代实验针对你的特定应用场景找到最适合的配置组合。从关闭图片加载和启用无头模式开始你通常能立即看到显著的提升然后再逐步深入更精细的等待策略、网络拦截和并行化优化。记住任何优化都要在保证功能正确性和脚本稳定性的前提下进行否则再快的脚本也是无用的。