Python Selenium自动化实战:从环境搭建到数据抓取完整指南 1. 项目概述为什么我们需要用代码控制浏览器作为一名和代码打了十几年交道的开发者我处理过无数需要从网页上获取数据、模拟用户操作或者进行界面测试的任务。早期我们可能依赖requests库抓取静态HTML或者用pyautogui模拟鼠标键盘。但这些方法要么无法处理JavaScript动态加载的内容要么脆弱得令人抓狂——屏幕分辨率一变脚本就全乱套了。直到我遇到了Selenium。它本质上是一个浏览器自动化工具而Python-Selenium的组合则像是一把万能钥匙让你能够用代码精准地指挥浏览器的一举一动打开网页、点击按钮、填写表单、滚动页面、甚至截屏和下载文件。这不仅仅是“自动化测试”的专利。想想这些场景你需要每天定时从某个需要登录的报表网站下载数据你需要监控几十个商品页面的价格变化或者你需要对一个内部Web应用进行重复性的功能操作。手动做枯燥且容易出错。用PythonSelenium写个脚本让它替你完成省下的时间和精力是实实在在的。这个项目的核心就是掌握用Python代码“遥控”浏览器的能力。它解决的痛点非常明确如何让程序像真人一样与复杂的、动态的现代网页进行交互。无论你是数据分析师、测试工程师、还是任何需要与网页打交道的开发者这项技能都能极大提升你的效率。接下来我会带你从零开始拆解这里面的每一个技术环节和实操细节。2. 环境搭建与核心工具选型解析工欲善其事必先利其器。用Python控制浏览器第一步就是把“武器库”准备好。这里面的选择看似简单但每一步都藏着影响后续稳定性的细节。2.1 Python环境与Selenium库安装Python环境是基石。我强烈建议使用Miniconda或Anaconda来管理环境它能完美解决不同项目间包版本冲突的问题。创建一个专用于本项目的独立环境是专业做法conda create -n selenium_env python3.9 conda activate selenium_env为什么是Python 3.9这是一个在稳定性和库兼容性上取得很好平衡的版本。太老的版本可能缺少新特性支持太新的版本如3.11有时会遇到一些底层库编译问题。选3.9或3.10作为起点比较稳妥。接下来安装Selenium库这很简单pip install selenium但这里有个关键注意事项不要只看selenium这个包。我们真正控制浏览器的桥梁是“浏览器驱动”。Selenium库只是一个发送指令的客户端而驱动才是那个直接操作浏览器的“翻译官”。驱动必须与你的浏览器版本严格匹配。2.2 浏览器与驱动的“配对”艺术这是新手最容易踩坑的地方。主流的三个选择是Chrome、Firefox和Edge。我以Chrome为例因为它市场占有率最高社区资源最丰富。查看你的Chrome版本打开Chrome点击右上角三个点 - 帮助 - 关于Google Chrome。记下版本号例如114.0.5735.199。下载对应驱动访问ChromeDriver的官方下载站点。这里切记驱动版本必须与浏览器的主版本号一致。对于上面的例子你需要下载版本号为114的ChromeDriver。放置驱动下载后是一个可执行文件Windows是.exemacOS/Linux是二进制文件。你有几种处理方式方式A推荐将驱动文件放在一个固定目录如C:\WebDriver\或/usr/local/bin/并将该目录添加到系统的PATH环境变量中。这是最干净的方法一劳永逸。方式B将驱动文件直接放在你的项目根目录下。在代码中指定驱动路径时使用相对路径即可。方式C使用webdriver-manager这个第三方库它可以自动检测浏览器版本并下载匹配的驱动。对于快速原型或不想手动管理驱动的场景非常方便。安装pip install webdriver-manager。对于Firefoxgeckodriver和Edgemsedgedriver流程完全类似都需要去各自的官方站点下载对应版本的驱动。实操心得在团队协作或部署到服务器时方式A固定PATH是最可靠的。它避免了因文件路径问题导致的脚本无法运行。个人学习阶段可以用webdriver-manager图个方便但了解手动配置的原理是必须的。2.3 集成开发环境IDE的选择写Python脚本一个好用的IDE能事半功倍。VS Code和PyCharm是两大主流。VS Code轻量、免费、插件生态极其丰富。对于本项目你需要安装Python扩展和Pylance扩展。它的优势是启动快配置灵活适合喜欢DIY的开发者。PyCharm功能强大开箱即用特别是其专业版对Web开发调试支持更好。它的智能提示、代码导航和调试器都非常优秀。社区版免费对于Selenium自动化开发已经足够。我的建议是如果你已经是某个IDE的深度用户继续用它就好。如果是从零开始VS Code的轻量化和免费特性可能更容易上手。无论选哪个确保配置好了Python解释器指向你刚创建的selenium_env环境。3. 核心操作从启动浏览器到元素定位环境就绪让我们真正开始“控制”浏览器。这个过程就像教一个机器人如何使用电脑首先得帮它打开电脑然后告诉它屏幕上的哪个按钮是你要点的。3.1 初始化WebDriver启动浏览器实例这是所有操作的起点。以下代码展示了三种主流浏览器的启动方式from selenium import webdriver from selenium.webdriver.common.by import By from webdriver_manager.chrome import ChromeDriverManager # 如果使用webdriver-manager import time # 方式1手动指定驱动路径推荐用于生产环境 driver_path r‘C:\WebDriver\chromedriver.exe’ # Windows示例 driver webdriver.Chrome(executable_pathdriver_path) # 注意新版本Selenium 4 语法有变 # Selenium 4 及以上版本的推荐写法无需指定executable_path from selenium.webdriver.chrome.service import Service service Service(executable_pathdriver_path) driver webdriver.Chrome(serviceservice) # 方式2使用webdriver-manager自动管理推荐用于学习和测试 from selenium.webdriver.chrome.service import Service as ChromeService from webdriver_manager.chrome import ChromeDriverManager driver webdriver.Chrome(serviceChromeService(ChromeDriverManager().install())) # 方式3启动Firefox from selenium.webdriver.firefox.service import Service as FirefoxService from webdriver_manager.firefox import GeckoDriverManager driver webdriver.Firefox(serviceFirefoxService(GeckoDriverManager().install())) # 方式4启动Edge from selenium.webdriver.edge.service import Service as EdgeService from webdriver_manager.microsoft import EdgeChromiumDriverManager driver webdriver.Edge(serviceEdgeService(EdgeChromiumDriverManager().install()))执行上述任何一段代码你都会看到一个新的浏览器窗口被打开。这个窗口是完全受你的程序控制的。driver这个对象就是你与这个浏览器实例通信的“遥控器”。3.2 页面导航与基础控制拿到“遥控器”后第一件事就是让浏览器去我们想去的地方。# 打开网页 driver.get(‘https://www.baidu.com’) print(f“当前页面标题{driver.title}”) print(f“当前页面URL{driver.current_url}”) # 浏览器窗口操作 driver.maximize_window() # 最大化窗口 driver.set_window_size(1200, 800) # 设置特定宽高 driver.minimize_window() # 最小化某些场景下有用 # 页面导航 driver.back() # 后退 driver.forward() # 前进 driver.refresh() # 刷新 # 关闭浏览器 driver.quit() # 关闭所有窗口并结束驱动进程彻底清理 # driver.close() # 仅关闭当前标签页如果只有一个标签页则效果同quit但不彻底重要区别driver.quit()和driver.close()。quit()会销毁整个WebDriver会话释放资源是结束操作的标准做法。close()只关闭当前窗口如果这是唯一窗口浏览器会关闭但驱动进程可能还在可能导致资源泄漏。养成用quit()的好习惯。3.3 元素定位自动化操作的“眼睛”这是Selenium最核心也最需要技巧的部分。你不能直接告诉程序“点那个登录按钮”你必须告诉它“点那个id是‘loginBtn’的按钮”。Selenium提供了8种主要的定位策略By类from selenium.webdriver.common.by import By # 假设我们有一个简单的登录页面 # input type“text” id“username” name“user” class“form-input” # button id“submitBtn”登录/button # 1. 通过ID定位最优先选择通常唯一且稳定 username_input driver.find_element(By.ID, “username”) # 2. 通过NAME定位 username_input driver.find_element(By.NAME, “user”) # 3. 通过CLASS_NAME定位注意class可能有多个用其中一个 input_element driver.find_element(By.CLASS_NAME, “form-input”) # 4. 通过TAG_NAME定位如 input, div, a all_inputs driver.find_elements(By.TAG_NAME, “input”) # 返回列表 # 5. 通过LINK_TEXT完整链接文本和 PARTIAL_LINK_TEXT部分链接文本定位 # a href“/about”关于我们/a about_link driver.find_element(By.LINK_TEXT, “关于我们”) about_link driver.find_element(By.PARTIAL_LINK_TEXT, “关于”) # 也可以 # 6. 通过CSS_SELECTOR定位功能强大语法灵活 username_input driver.find_element(By.CSS_SELECTOR, “#username”) # ID选择器 username_input driver.find_element(By.CSS_SELECTOR, “input.form-input”) # 组合选择器 submit_btn driver.find_element(By.CSS_SELECTOR, “button#submitBtn”) # 标签ID # 7. 通过XPATH定位功能最强大但可能较慢且脆弱 username_input driver.find_element(By.XPATH, “//input[id‘username’]”) username_input driver.find_element(By.XPATH, “//*[id‘username’]”) submit_btn driver.find_element(By.XPATH, “//button[text()‘登录’]”) # 按文本定位定位策略选择优先级个人经验ID Name如果元素有唯一ID或Name毫不犹豫用它。速度最快最稳定。CSS Selector这是我最常用的“瑞士军刀”。它的语法比XPath简洁在现代浏览器中解析速度通常更快。对于复杂的组合条件如“某个div下的第一个input”CSS选择器非常得心应手。XPath当元素没有好的ID/Class或者需要根据文本内容、复杂层级关系定位时XPath是终极武器。但尽量使用相对XPath以//开头避免使用包含索引的绝对路径如/html/body/div[3]/div[2]/input因为页面结构一变这种路径就失效了。Class Name, Tag Name通常用于批量获取元素或作为CSS/XPath的一部分。Link Text专门用于定位超链接。find_element返回第一个匹配的元素find_elements返回所有匹配元素的列表。操作前务必判断元素是否存在或是否可交互这涉及到下一节的“等待”策略。4. 高级交互等待、帧切换与文件操作掌握了定位我们就可以让浏览器“动”起来了。但直接操作常常会遇到问题页面还没加载完脚本就去点击按钮结果报错“元素不可交互”。因此“等待”是稳定自动化的灵魂。4.1 三种等待策略详解强制等待time.sleeptime.sleep(5)。这是最原始的方法让程序无条件暂停指定秒数。不推荐在正式脚本中使用因为它效率低下且不可靠网络慢时可能不够网络快时又浪费时间。隐式等待Implicit Waitdriver.implicitly_wait(10) # 设置一次全局生效 element driver.find_element(By.ID, “someId”)它告诉WebDriver在查找任何元素时如果没立即找到就轮询DOM一段时间这里10秒直到找到或超时。它只对find_element这类查找操作有效。缺点它无法处理元素存在但不可点击如被遮挡、未启用的情况。显式等待Explicit Wait这是工业级自动化推荐的做法。它允许你为某个特定条件设置等待条件满足则继续超时则报错。功能强大且精准。from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC # 等待元素出现在DOM中并可点击 wait WebDriverWait(driver, 10) # 最长等10秒 login_button wait.until(EC.element_to_be_clickable((By.ID, “loginBtn”))) login_button.click() # 等待元素可见 element wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, “.result”))) # 等待元素包含特定文本 element wait.until(EC.text_to_be_present_in_element((By.ID, “status”), “成功”)) # 等待新窗口出现 wait.until(EC.number_of_windows_to_be(2))expected_conditionsEC模块提供了大量预定义条件。显式等待能精准控制脚本节奏是编写健壮自动化脚本的关键。4.2 复杂交互鼠标、键盘与下拉框Selenium的ActionChains和Keys类让我们能模拟更复杂的用户行为。from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.keys import Keys from selenium.webdriver.support.ui import Select # 鼠标悬停 menu driver.find_element(By.ID, “dropdownMenu”) submenu driver.find_element(By.ID, “subItem”) actions ActionChains(driver) actions.move_to_element(menu).pause(1).click(submenu).perform() # 拖放操作 source driver.find_element(By.ID, “draggable”) target driver.find_element(By.ID, “droppable”) actions.drag_and_drop(source, target).perform() # 键盘操作 input_box driver.find_element(By.ID, “search”) input_box.send_keys(“Selenium自动化”) # 输入文本 input_box.send_keys(Keys.CONTROL, ‘a’) # 全选 (CtrlA) input_box.send_keys(Keys.BACKSPACE) # 删除 input_box.send_keys(Keys.ENTER) # 回车 # 处理下拉选择框Select标签 select_element driver.find_element(By.ID, “country”) select Select(select_element) select.select_by_visible_text(“中国”) # 按文本选择 select.select_by_value(“CN”) # 按value属性选择 select.select_by_index(1) # 按索引选择从0开始4.3 处理弹窗、帧iframe与多窗口现代网页应用充满了各种“套娃”结构。处理JavaScript弹窗Alert, Confirm, Prompt# 触发一个alert driver.find_element(By.ID, “alertBtn”).click() # 切换到alert alert driver.switch_to.alert print(alert.text) # 获取弹窗文本 alert.accept() # 点击“确定” # alert.dismiss() # 点击“取消” # alert.send_keys(“输入内容”) # 针对prompt弹窗输入处理iframe/框架 如果元素位于一个iframe或frame标签内你必须先切换到该帧才能定位其中的元素。# 通过ID或Name切换 driver.switch_to.frame(“iframeId”) # 通过索引切换从0开始 driver.switch_to.frame(0) # 通过WebElement切换 frame_element driver.find_element(By.CSS_SELECTOR, “iframe.modal-frame”) driver.switch_to.frame(frame_element) # 操作iframe内的元素 driver.find_element(By.ID, “innerButton”).click() # 操作完成后切回主文档 driver.switch_to.default_content()处理多标签页/多窗口# 获取当前窗口句柄 main_window driver.current_window_handle # 点击一个打开新窗口的链接 driver.find_element(By.LINK_TEXT, “在新窗口打开”).click() # 获取所有窗口句柄 all_windows driver.window_handles # 切换到新窗口 for window in all_windows: if window ! main_window: driver.switch_to.window(window) break # 在新窗口操作 print(driver.title) # 关闭新窗口切回主窗口 driver.close() driver.switch_to.window(main_window)4.4 文件上传与下载文件上传对于input type“file”元素直接使用send_keys传入文件本地绝对路径即可。千万不要尝试用ActionChains或点击去触发系统文件选择框那是操作系统级别的Selenium无法控制。upload_input driver.find_element(By.ID, “fileUpload”) upload_input.send_keys(r“C:\Users\YourName\Desktop\test.pdf”)文件下载控制浏览器的下载行为需要设置Chrome选项。from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options Options() prefs { “download.default_directory”: r“C:\Downloads\Selenium”, # 设置下载路径 “download.prompt_for_download”: False, # 禁止下载确认弹窗 “download.directory_upgrade”: True, “safebrowsing.enabled”: True } chrome_options.add_experimental_option(“prefs”, prefs) driver webdriver.Chrome(optionschrome_options)设置好后点击下载链接文件会自动保存到指定目录。你可以用Python的os模块去检查文件是否已下载完成。5. 实战案例模拟登录与数据抓取让我们用一个完整的实战案例串联起前面所有的知识点。假设我们要自动化登录一个模拟的电商网站并抓取用户订单列表的第一页数据。5.1 案例场景与目标分析目标网站一个需要登录才能查看订单的电商平台。 任务步骤打开登录页面。输入用户名和密码。处理可能的验证码本例假设为简单图片验证码我们先手动处理一次后续可探讨简单识别方案。点击登录等待跳转完成。导航到“我的订单”页面。等待订单列表加载。解析列表中的每一行订单数据订单号、日期、金额、状态。将数据保存到CSV文件。实现翻页抓取可选。5.2 分步代码实现与讲解import time import csv 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.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager class EcommerceOrderScraper: def __init__(self): # 使用webdriver-manager自动管理驱动 self.driver webdriver.Chrome(serviceService(ChromeDriverManager().install())) self.wait WebDriverWait(self.driver, 15) # 设置一个全局显式等待 self.driver.maximize_window() def login(self, username, password): “”“执行登录操作”“” print(“正在打开登录页面...”) self.driver.get(“https://demo.ecommerce.com/login”) # 假设的网址 # 1. 定位并填写用户名 # 使用显式等待确保元素可交互 username_input self.wait.until( EC.element_to_be_clickable((By.CSS_SELECTOR, “input[name‘username’]”)) ) username_input.clear() username_input.send_keys(username) print(“用户名已输入”) # 2. 定位并填写密码 password_input self.driver.find_element(By.CSS_SELECTOR, “input[type‘password’]”) password_input.send_keys(password) print(“密码已输入”) # 3. 处理验证码这里以手动输入为例 # 假设验证码图片在一个img标签里旁边有一个输入框 captcha_img self.driver.find_element(By.ID, “captchaImage”) # 这里可以添加截图保存验证码的代码方便手动查看 # captcha_img.screenshot(‘captcha.png’) print(“请查看页面上的验证码并手动输入...”) time.sleep(15) # 给予15秒时间手动输入验证码 # 在实际自动化中这里可以集成简单的OCR库如pytesseract进行识别但复杂验证码需要更高级方案。 # 4. 点击登录按钮 login_btn self.driver.find_element(By.XPATH, “//button[contains(text(), ‘登录’)]”) login_btn.click() print(“点击登录按钮”) # 5. 等待登录成功例如等待用户头像或‘我的账户’链接出现 try: self.wait.until( EC.presence_of_element_located((By.LINK_TEXT, “我的账户”)) ) print(“登录成功”) return True except Exception as e: print(f“登录失败{e}”) # 可以在这里截图保存错误现场 self.driver.save_screenshot(“login_error.png”) return False def scrape_orders(self, max_pages3): “”“抓取订单数据”“” if not self.is_logged_in(): print(“未登录无法抓取订单”) return print(“正在导航到订单页面...”) # 点击‘我的订单’链接 order_link self.wait.until( EC.element_to_be_clickable((By.PARTIAL_LINK_TEXT, “我的订单”)) ) order_link.click() all_orders [] current_page 1 while current_page max_pages: print(f“正在抓取第 {current_page} 页...”) # 等待订单表格加载 self.wait.until( EC.visibility_of_element_located((By.CSS_SELECTOR, “table.orders-table tbody”)) ) # 定位表格行 order_rows self.driver.find_elements(By.CSS_SELECTOR, “table.orders-table tbody tr”) if not order_rows: print(“未找到订单数据。”) break for row in order_rows: # 假设每行有4列订单号、日期、金额、状态 cols row.find_elements(By.TAG_NAME, “td”) if len(cols) 4: order_data { “order_no”: cols[0].text.strip(), “date”: cols[1].text.strip(), “amount”: cols[2].text.strip(), “status”: cols[3].text.strip() } all_orders.append(order_data) print(f“抓取到订单{order_data}”) # 尝试翻页 try: next_button self.driver.find_element(By.CSS_SELECTOR, “a.next-page:not(.disabled)”) next_button.click() # 等待新页面加载例如等待旧页面的某个元素消失或新页面的某个元素出现 self.wait.until( EC.staleness_of(order_rows[0]) # 等待第一行元素“过时”即页面已刷新 ) current_page 1 time.sleep(2) # 翻页后稍作等待让数据稳定 except: print(“已到最后一页或找不到下一页按钮。”) break return all_orders def is_logged_in(self): “”“检查是否处于登录状态”“” try: # 尝试查找登录后才有的元素 self.driver.find_element(By.LINK_TEXT, “我的账户”) return True except: return False def save_to_csv(self, orders, filename“orders.csv”): “”“将订单数据保存到CSV文件”“” if not orders: print(“没有数据可保存。”) return keys orders[0].keys() with open(filename, ‘w’, newline‘’, encoding‘utf-8-sig’) as f: # utf-8-sig解决Excel中文乱码 writer csv.DictWriter(f, fieldnameskeys) writer.writeheader() writer.writerows(orders) print(f“数据已保存到 {filename}共 {len(orders)} 条记录。”) def run(self, username, password): “”“主运行流程”“” try: if self.login(username, password): orders self.scrape_orders(max_pages2) # 抓取前2页 self.save_to_csv(orders) else: print(“程序因登录失败而终止。”) except Exception as e: print(f“程序运行出现异常{e}”) self.driver.save_screenshot(“error_screenshot.png”) # 异常时截图 finally: # 无论成功与否最后都关闭浏览器 time.sleep(3) self.driver.quit() if __name__ “__main__”: scraper EcommerceOrderScraper() # 请替换为你的测试账号 scraper.run(“your_username”, “your_password”)5.3 案例中的关键技巧与避坑点使用Page Object Model (POM) 设计模式上面的代码将登录和抓取逻辑写在了类里这是一个简化版。在更复杂的项目中强烈建议使用POM模式将每个页面的元素定位和操作封装成单独的类使代码更易维护和复用。显式等待是核心注意代码中大量使用了WebDriverWait和EC。这确保了脚本在元素准备好之后才进行操作避免了NoSuchElementException等常见错误。健壮的错误处理在登录判断、翻页等可能失败的地方使用了try...except。并且在异常时截图save_screenshot这对于调试无人值守的脚本至关重要。处理动态内容订单列表可能是通过Ajax加载的。我们通过等待表格体tbody可见来确保数据已加载。翻页时使用EC.staleness_of等待旧元素失效是判断页面已刷新的好方法。验证码处理这是一个难点。示例中给出了手动处理的方案。对于简单数字字母验证码可以结合pytesseractOCR库尝试识别但成功率并非100%。对于复杂验证码如滑块、点选可能需要引入更专业的打码平台服务这超出了基础范围。在实际项目中评估验证码策略是必须的。6. 常见问题排查与性能优化即使按照最佳实践编写脚本依然会遇到各种稀奇古怪的问题。这里我总结了一份“排错手册”和优化建议。6.1 高频错误与解决方案速查表错误信息/现象可能原因解决方案selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element1. 元素定位器写错了。2. 页面尚未加载完成就去查找元素。3. 元素在iframe或shadow DOM内。4. 元素是动态生成的定位方式不唯一。1. 用浏览器开发者工具F12的Copy - Copy selector或Copy XPath复核定位器。2.添加显式等待WebDriverWaitEC.presence/visibility_of...。3. 使用driver.switch_to.frame()切换到对应iframe。4. 使用更稳定的定位方式如结合父元素的唯一属性。selenium.common.exceptions.ElementNotInteractableException: Message: element not interactable1. 元素被其他元素遮挡如弹窗、遮罩层。2. 元素不可见style“display: none;”。3. 元素未启用disabled属性。1. 等待遮挡层消失或手动关闭它。2. 等待元素变为可见EC.visibility_of...。3. 检查元素状态或通过JavaScript直接操作driver.execute_script(“arguments[0].click();”, element)。selenium.common.exceptions.StaleElementReferenceException之前找到的元素因为页面刷新或重新渲染已经“过时”了。重新定位元素。在每次使用元素前特别是在页面刷新或Ajax操作后重新执行find_element。避免将元素对象长期存储。selenium.common.exceptions.TimeoutException显式等待的条件在指定时间内未满足。1. 增加等待时间。2. 检查等待条件是否正确如元素定位器。3. 页面可能发生了非预期的跳转或错误。脚本在本地运行成功在服务器/别人电脑上失败1. 浏览器版本与驱动版本不匹配。2. 浏览器未安装或无头模式配置问题。3. 屏幕分辨率/缩放比例不同影响点击坐标。1. 确保环境一致使用webdriver-manager或固定版本。2. 服务器上使用无头模式ChromeOptions().add_argument(‘--headless’)并确保安装了浏览器。3. 尽量使用基于元素的交互click()而非基于坐标的交互。文件下载不成功浏览器下载弹窗未被正确处理或下载路径无权限。1. 正确配置Chrome选项禁用下载弹窗并设置默认路径见4.4节。2. 确保下载目录存在且有写入权限。3. 下载后添加等待使用os.path.exists()检查文件是否完整。6.2 脚本性能与稳定性优化使用无头模式Headless Mode在服务器运行或不需要观察界面时使用无头模式可以节省大量资源并避免图形界面带来的潜在问题。from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_argument(‘--headless’) # 启用无头模式 chrome_options.add_argument(‘--disable-gpu’) # 某些系统需要 chrome_options.add_argument(‘--no-sandbox’) # Linux系统下可能需要 chrome_options.add_argument(‘--disable-dev-shm-usage’) # 解决共享内存问题 driver webdriver.Chrome(optionschrome_options)优化等待策略混合使用隐式和显式等待可以设置一个较短的全局隐式等待如5秒作为兜底在关键操作处使用更精确的显式等待。避免time.sleep除非是等待固定动画或手动干预如输验证码否则用显式等待替代。使用更具体的等待条件例如等待元素可点击element_to_be_clickable比等待元素存在presence_of_element_located更好因为它确保了元素不仅存在而且处于可交互状态。复用浏览器会话对于需要多次登录或状态保持的复杂任务可以考虑手动启动一个带用户数据目录的浏览器然后使用Selenium连接它避免每次重新登录。# 首先手动启动Chrome带远程调试端口 # chrome.exe --remote-debugging-port9222 --user-data-dir“C:\SeleniumProfile” # 然后在Python中连接这个已有实例 from selenium import webdriver from selenium.webdriver.chrome.options import Options chrome_options Options() chrome_options.add_experimental_option(“debuggerAddress”, “127.0.0.1:9222”) driver webdriver.Chrome(optionschrome_options) # 此时driver控制的浏览器已经是你手动打开的那个带有所有cookies和登录状态这种方法非常强大但需要注意端口冲突和会话管理。合理管理Driver生命周期确保脚本结束时调用driver.quit()特别是在try...except...finally块中将quit()放在finally里防止因异常导致浏览器进程残留。处理反爬虫机制一些网站会检测Selenium特征。可以尝试添加一些选项来“隐藏”自己chrome_options.add_argument(‘--disable-blink-featuresAutomationControlled’) chrome_options.add_experimental_option(“excludeSwitches”, [“enable-automation”]) chrome_options.add_experimental_option(‘useAutomationExtension’, False) # 此外可以修改navigator.webdriver属性需在CDP中执行 driver.execute_cdp_cmd(‘Page.addScriptToEvaluateOnNewDocument’, { ‘source’: ‘ Object.defineProperty(navigator, ‘webdriver’, { get: () undefined }); ‘ })但请注意这只是基础规避高级反爬策略需要更复杂的对抗手段。掌握了这些核心操作、实战技巧和排错方法你已经能够用PythonSelenium应对绝大多数浏览器自动化需求了。从简单的数据抓取到复杂的业务流程模拟这套工具组合都能为你提供强大的支持。关键在于多实践在真实的项目中遇到问题、解决问题你的经验才会真正积累起来。