Web自动化测试中验证码处理与Cookie管理的实战策略

📅 2026/7/6 23:40:41
Web自动化测试中验证码处理与Cookie管理的实战策略
1. 项目概述当自动化测试遇上验证码与Cookie做Web UI自动化测试的朋友估计都绕不开两个“老大难”问题验证码处理和Cookie管理。标题里的“12_web自动化测试 _验证码处理和cookie”一看就是某个系列课程或实战总结的第十二章核心就是解决这两个在自动化脚本中高频出现、又让人头疼的拦路虎。这不仅仅是写几行代码点个按钮那么简单它背后涉及的是对Web应用安全机制的理解、对HTTP协议会话状态的掌控以及在实际项目中如何设计出既稳定又灵活的测试策略。简单来说验证码是系统用来区分人和机器的而Cookie是浏览器用来维持用户状态的。我们的自动化脚本作为“机器”要模拟“人”的操作就必须找到合适的方法绕过或处理验证码同时又要像真人浏览器一样正确地携带和使用Cookie保持登录态、传递用户偏好。处理不好脚本要么卡在登录页要么动不动就掉线测试的稳定性和效率无从谈起。这篇文章我就结合自己趟过的坑把验证码处理和Cookie管理的核心思路、常见方案以及那些文档里不会写的实操细节给你掰开揉碎了讲清楚。无论你是刚接触UI自动化的新手还是想优化现有框架的老手这里都有你能直接拿去用的“解药”。2. 验证码处理从“硬刚”到“智取”的实战策略验证码的存在本质上是为了增加自动化攻击的成本保护系统安全。但对于自动化测试而言它就成了一个必须跨越的障碍。处理验证码没有银弹需要根据验证码的类型、复杂度和项目实际情况来选择策略。核心原则是在保证测试目的的前提下寻求最高效、最稳定的解决方案而不是追求百分百的通用识别。2.1 常见验证码类型与应对思路分析首先我们得知道自己面对的是什么“敌人”。常见的Web验证码主要有以下几种数字/字母图片验证码最经典的形式由扭曲、粘连的数字字母组成可能有背景干扰线。早期很多系统使用现在逐渐减少但仍有存量。滑动拼图验证码需要将缺失的拼图块拖动到正确位置。考验的是对图像缺口位置的识别和模拟拖动轨迹。点选文字验证码给出图片和一组文字要求按顺序点击图片中指定的文字。难点在于文字识别和坐标定位。算术验证码如“35”需要计算并输入结果。通常比较简单但需要解析图片中的算式。行为验证码如极验、腾讯云验证码集成了多种交互如滑动、点选、推理等背后有复杂的行为分析模型防御能力最强。短信/邮箱验证码需要从短信或邮件中提取动态码。这涉及到另一个通道手机收件箱或邮件服务器的信息获取。对于测试而言我们的目标不是破解验证码那是安全研究的范畴而是让测试流程能顺利进行下去。因此策略上可以分为几个层次绕过/禁用这是最理想的情况需要开发配合。在测试环境为特定的测试账号或IP地址设置白名单或者提供一个万能验证码如“0000”。后端接口获取有些系统在生成验证码的同时会有一个仅供内部或测试使用的接口返回验证码的明文。这是最稳定可靠的方式。OCR识别对于简单的图形验证码使用光学字符识别技术。识别成功率受图片复杂度影响大。第三方打码平台将验证码图片发送到专业平台由人工或高精度模型识别后返回结果。需要付费但稳定性和通用性较好。Cookie/Session跳过对于登录后的操作测试有时可以手动登录一次然后获取有效的Cookie直接用于脚本完全避开登录环节。注意在选择任何识别方案前务必与项目负责人、开发人员沟通并确认其符合法律法规和公司安全政策。严禁对生产环境或他人系统进行未经授权的自动化识别尝试。2.2 实战方案一测试环境万能验证码与后端接口调用这是成本最低、稳定性最高的方案应作为首选。场景你拥有测试环境的部署权限或能与开发团队紧密协作。操作步骤沟通确认向开发团队提出需求说明自动化测试需要稳定绕过验证码。建议的方案是在测试环境部署时通过配置文件开关控制验证码的难度或者为测试专用的账号/IP设置验证码白名单。实现万能验证码让开发在验证码校验逻辑中增加一个判断如果输入的验证码是某个特定字符串如“test”或“automation”则直接校验通过。你在脚本中固定输入这个字符串即可。调用后端接口如果系统有验证码生成接口例如/api/captcha/generate通常也会有一个配套的获取接口例如/api/captcha/value?keyxxx。你需要首先调用生成接口获取一个本次验证码对应的唯一key可能放在响应头、Cookie或响应体里。然后调用获取接口传入这个key获取明文的验证码。在UI页面上输入这个验证码。这里的关键是模拟浏览器行为处理好接口调用与页面操作之间的Session或Token关联。Python Selenium 示例假设有获取接口import requests from selenium import webdriver driver webdriver.Chrome() driver.get(https://test.example.com/login) # 1. 首先可能需要从页面中获取生成验证码时使用的token或key # 例如可能隐藏在某个img标签的data-key属性里或者由前端JS生成 captcha_img driver.find_element(By.ID, “captcha-img”) captcha_key captcha_img.get_attribute(“data-key”) # 假设如此 # 2. 调用后端接口获取明文验证码注意处理Cookie同步 session requests.Session() # 将Selenium驱动当前页面的Cookie同步到requests session selenium_cookies driver.get_cookies() for cookie in selenium_cookies: session.cookies.set(cookie[‘name’], cookie[‘value’]) # 调用获取验证码的接口 api_url f“https://test.example.com/api/captcha/value?key{captcha_key}” response session.get(api_url) captcha_text response.text # 假设接口直接返回文本 # 3. 在页面上输入验证码 driver.find_element(By.ID, “captcha-input”).send_keys(captcha_text) # ... 继续输入用户名密码并登录实操心得与开发定好规范比如万能验证码的字符串、接口的路径和参数并写入项目的测试Wiki避免后续人员不知情。使用requests.Session()可以自动管理Cookie确保接口调用和浏览器操作处在同一个会话中这是模拟关联请求的关键。如果接口需要额外的认证头如Token可能需要从页面JavaScript变量或网络请求中提取。2.3 实战方案二OCR识别与第三方打码平台集成当无法从后端直接获取验证码时我们才考虑识别方案。对于简单图片验证码OCR 可以使用开源的Tesseract OCR库但识别率对图片质量要求高。通常需要先对图片进行预处理。预处理识别步骤截图定位并截取验证码图片元素。预处理转灰度、二值化、降噪、去除干扰线、字符分割。这一步非常关键直接决定识别成功率。识别使用Tesseract或其它OCR引擎进行识别。后处理根据验证码可能的字符集如纯数字对识别结果进行校正。Python示例使用pytesseract和PILfrom PIL import Image, ImageFilter, ImageEnhance import pytesseract from selenium import webdriver driver webdriver.Chrome() driver.get(“login_page_url”) # 定位验证码元素并截图 captcha_element driver.find_element(By.ID, “captcha-img”) captcha_element.screenshot(‘captcha.png’) # 图像预处理 image Image.open(‘captcha.png’) # 转灰度 image image.convert(‘L’) # 二值化 (阈值可根据实际情况调整) threshold 150 image image.point(lambda p: p threshold and 255) # 降噪 (中值滤波) image image.filter(ImageFilter.MedianFilter(size3)) # 增强对比度 enhancer ImageEnhance.Contrast(image) image enhancer.enhance(2.0) image.save(‘captcha_processed.png’) # OCR识别并配置只识别数字如果验证码是数字 custom_config r’--oem 3 --psm 7 -c tessedit_char_whitelist0123456789’ captcha_text pytesseract.image_to_string(image, configcustom_config).strip() print(f“识别结果: {captcha_text}”) # 输入识别结果 driver.find_element(By.ID, “captcha-input”).send_keys(captcha_text)对于复杂验证码或追求稳定性 推荐使用第三方打码平台如超级鹰、图鉴等。流程通常是注册平台获取软件ID和密钥。将验证码图片字节流或Base64编码通过平台API发送。平台返回识别结果。将结果输入页面。优点识别率高专人维护模型支持种类多。缺点产生费用有网络依赖。集成打码平台的核心代码逻辑import base64 import requests def identify_captcha_with_platform(image_path, platform_config): “””调用第三方打码平台””” with open(image_path, ‘rb’) as f: img_bytes f.read() # 通常平台要求base64编码 b64_data base64.b64encode(img_bytes).decode(‘utf-8’) # 构造请求参数 (以某个平台为例具体看API文档) data { ‘username’: platform_config[‘username’], ‘password’: platform_config[‘password’], ‘typeid’: ‘1001’, # 验证码类型编号如1001代表4位数字字母 ‘image’: b64_data } resp requests.post(‘http://api.example.com/decode’, datadata) result resp.json() if result[‘success’]: return result[‘data’][‘code’] # 返回识别结果 else: raise Exception(f“打码失败: {result[‘message’]}”)踩坑记录识别率问题本地OCR对扭曲、粘连严重的验证码基本无效。不要花太多时间调优不如直接考虑打码平台。成本控制打码平台通常按次计费。在脚本调试阶段频繁失败会浪费次数。建议在调试时先使用万能验证码或手动处理脚本稳定后再切换。异步加载验证码图片可能是点击后动态生成的需要确保在截图前图片已经加载完成。使用WebDriverWait等待元素可见或具备特定属性。超时与重试识别过程可能失败需要加入重试机制。例如识别后提交登录如果页面提示验证码错误则刷新验证码重新识别最多重试3次。2.4 实战方案三Cookie跳过登录与滑动验证码处理Cookie跳过登录这其实不是处理验证码而是完全规避了登录流程。适用于测试登录后功能的场景。操作流程手动用浏览器正常登录一次系统。打开开发者工具F12进入Application或存储选项卡找到Cookies选择当前网站的域名。你会看到一个Cookie列表。你需要找到那些用于维持登录态的关键Cookie通常是sessionid,token,auth等名称。将它们全部复制出来可以右键Copy All但注意格式。在你的自动化脚本启动浏览器后在访问登录页或首页之前通过driver.add_cookie()方法将这些Cookie添加到WebDriver中。添加完成后刷新页面或跳转到目标页此时应该已经是登录状态。Python Selenium 示例from selenium import webdriver import json driver webdriver.Chrome() driver.get(“https://target-website.com”) # 先访问域名以便浏览器设置Cookie的域名上下文 # 加载之前保存的Cookie文件 (手动登录后通过插件或脚本导出的JSON) with open(‘cookies.json’, ‘r’) as f: cookies json.load(f) for cookie in cookies: # 添加前可能需要删除‘sameSite’等Selenium不支持的属性 if ‘sameSite’ in cookie: if cookie[‘sameSite’] ‘None’: cookie[‘sameSite’] ‘Lax’ # 或直接删除该字段 try: driver.add_cookie(cookie) except Exception as e: print(f“添加Cookie {cookie[‘name’]} 时出错: {e}”) # 添加完Cookie后刷新页面或跳转到需要登录的页面 driver.refresh() # 或者 driver.get(“https://target-website.com/dashboard”) # 此时应已处于登录状态重要提示Cookie有生命周期过期时间expiry和域名限制domain。确保你添加的Cookie对当前驱动访问的域名有效且未过期。过期时间是一个Unix时间戳。滑动验证码处理对于滑动拼图验证码核心是计算缺口位置并模拟人的滑动轨迹。处理步骤获取背景图和缺口图通常可以通过元素定位获取两张图片的src属性然后下载或转换为PIL Image对象。识别缺口位置这是最关键的步骤。可以使用图像处理库如OpenCV进行模板匹配。将小的缺口图滑块在大的背景图上滑动找到最匹配的位置其X轴偏移量就是需要滑动的距离。模拟滑动计算出滑动距离后不能简单地将滑块瞬间移动到终点因为会被检测为机器操作。需要模拟人的滑动轨迹先加速再匀速最后减速。使用Selenium的ActionChains来拖拽元素。Python OpenCV Selenium 示例import cv2 import numpy as np from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By import time, requests from io import BytesIO from PIL import Image driver webdriver.Chrome() driver.get(“login_page_with_slide”) # 1. 获取背景图和滑块图URL bg_img_url driver.find_element(By.CLASS_NAME, “bg-img”).get_attribute(“src”) slide_img_url driver.find_element(By.CLASS_NAME, “slide-img”).get_attribute(“src”) # 2. 下载图片并转换为OpenCV格式 bg_resp requests.get(bg_img_url) slide_resp requests.get(slide_img_url) bg_image cv2.imdecode(np.frombuffer(bg_resp.content, np.uint8), cv2.IMREAD_COLOR) slide_image cv2.imdecode(np.frombuffer(slide_resp.content, np.uint8), cv2.IMREAD_COLOR) # 3. 使用模板匹配找出缺口位置 result cv2.matchTemplate(bg_image, slide_image, cv2.TM_CCOEFF_NORMED) min_val, max_val, min_loc, max_loc cv2.minMaxLoc(result) slide_length max_loc[0] # 匹配位置的x坐标即缺口起始位置 # 注意网页上的图片可能经过缩放需要计算缩放比例 # 获取网页上背景图元素的真实宽度 bg_element driver.find_element(By.CLASS_NAME, “bg-img”) bg_width bg_element.size[‘width’] # 获取原始背景图片的宽度 bg_img_original_width bg_image.shape[1] scale bg_width / bg_img_original_width # 计算在网页上需要滑动的实际距离 slide_distance slide_length * scale # 4. 模拟人的滑动轨迹 slider driver.find_element(By.CLASS_NAME, “slider-button”) action ActionChains(driver) action.click_and_hold(slider).perform() # 模拟滑动轨迹先加速后减速 total_tracks [] current 0 mid slide_distance * 0.8 t 0.2 v 0 while current slide_distance: if current mid: a 2 # 加速度 else: a -3 # 减速度 s v * t 0.5 * a * t * t v v a * t current s total_tracks.append(round(s)) # 执行滑动 for track in total_tracks: action.move_by_offset(track, 0).perform() time.sleep(t/10) # 加入微小间隔更拟人 action.release().perform() time.sleep(1) # 等待验证结果注意事项缩放比例网页显示的图片尺寸和原始图片尺寸可能不同必须计算缩放比例否则滑动距离会错。轨迹检测高级的反爬系统会检测滑动轨迹是否符合人类特征。上述的匀加速-匀减速模型是基础更复杂的系统可能需要更随机的轨迹甚至加入Y轴的微小抖动。动态加载有些验证码的缺口位置每次会随机变化需要每次重新计算。失败重试滑动验证可能因为轨迹或位置计算偏差而失败需要加入判断如检查是否出现成功提示和重试逻辑。3. Cookie管理维持会话状态的基石如果说验证码是门卫那Cookie就是你的门禁卡。在Web自动化中Cookie管理不好就会出现“登录状态丢失”、“页面跳转后数据没了”等问题。理解Cookie的工作原理并能在Selenium中熟练操作是编写稳定自动化脚本的基础。3.1 Cookie的核心概念与在自动化中的重要性Cookie是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器下次向同一服务器再发起请求时会自动携带Cookie服务器据此识别用户身份和状态。在自动化测试中Cookie管理主要涉及登录状态保持登录成功后服务器会下发包含会话ID如JSESSIONID,PHPSESSID或Token的Cookie。后续所有请求携带这个Cookie服务器就知道你是谁。用户偏好记录如语言设置、主题样式等。跟踪与统计一些分析工具会使用Cookie。为什么在自动化中要专门管理Cookie效率避免每次测试都从头执行完整的登录流程尤其是需要验证码时。稳定性直接使用有效的Cookie可以绕过不稳定的登录环节。测试特定场景测试Cookie过期、失效、篡改等安全相关用例。多环境切换在不同环境测试、预发布使用不同的认证Cookie。3.2 Selenium操作Cookie的完整API详解Selenium WebDriver提供了完整的Cookie操作API功能非常直接。获取所有Cookieall_cookies driver.get_cookies() # 返回一个列表每个元素是一个字典包含‘name’, ‘value’, ‘domain’, ‘path’, ‘expiry’(Unix时间戳), ‘secure’, ‘httpOnly’等键。 print(all_cookies)获取指定名称的Cookiespecific_cookie driver.get_cookie(‘sessionid’) # 返回一个字典如果不存在则返回None。添加Cookie# 添加一个Cookie。注意添加Cookie前driver必须已经访问过该Cookie所属的域名。 driver.add_cookie({ ‘name’: ‘my_cookie’, ‘value’: ‘cookie_value’, ‘domain’: ‘.example.com’, # 可选默认为当前域名 ‘path’: ‘/’, # 可选 ‘secure’: True, # 可选仅HTTPS ‘httpOnly’: False, # 可选脚本是否可访问 ‘expiry’: 1740816000 # 可选过期时间戳 })关键点driver.add_cookie()必须在当前浏览器会话的域名上下文与Cookie的domain匹配时才能成功。通常的做法是先driver.get(“https://domain.com”)访问一下该域名的主页然后再添加Cookie。删除Cookie# 删除指定Cookie driver.delete_cookie(‘cookie_name’) # 删除所有Cookie driver.delete_all_cookies()3.3 实战Cookie的持久化、复用与失效处理单纯会操作API还不够要在项目中用好Cookie需要一套管理策略。场景一Cookie持久化与复用实现免登录这是最常用的技巧。将手动登录后获取的Cookie保存到文件如JSON后续脚本运行时直接加载。步骤手动登录并导出Cookie。可以写一个简单的脚本在手动登录后执行将driver.get_cookies()的结果保存为JSON文件。# save_cookies.py from selenium import webdriver import json, time driver webdriver.Chrome() driver.get(“https://your-test-site.com/login”) input(“请手动完成登录然后按回车键继续...”) # 登录后Cookie已设置 cookies driver.get_cookies() with open(‘cookies.json’, ‘w’) as f: json.dump(cookies, f) print(“Cookie已保存至cookies.json”) driver.quit()在自动化脚本中加载Cookie。脚本启动后先访问目标域名然后加载Cookie文件。# test_with_cookies.py from selenium import webdriver import json def create_driver_with_cookies(cookie_file_path): driver webdriver.Chrome() # 必须先访问域名哪怕是个空白页以建立正确的域名上下文 driver.get(“https://your-test-site.com/”) # 删除可能存在的旧Cookie避免冲突 driver.delete_all_cookies() with open(cookie_file_path, ‘r’) as f: cookies json.load(f) for cookie in cookies: # 处理可能存在的‘expiry’类型问题JSON保存后可能是float 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}”) # 再次访问目标页面此时应携带Cookie driver.get(“https://your-test-site.com/dashboard”) return driver driver create_driver_with_cookies(‘cookies.json’) # 此时driver应处于登录状态可以开始后续测试场景二Cookie失效的自动检测与重新登录Cookie会过期。脚本不能假设Cookie永远有效必须有容错机制。策略启动时检查加载Cookie后访问一个需要登录的API或页面检查返回内容或页面元素判断是否仍处于登录状态。操作中检查在关键操作如提交表单前可以检查页面上是否存在登录相关的元素如用户头像、退出按钮。失败后重试如果检测到未登录则触发重新登录流程可能需要处理验证码并更新Cookie文件。示例代码框架class AutoTestWithCookie: def __init__(self, cookie_file‘cookies.json’): self.cookie_file cookie_file self.driver webdriver.Chrome() self.is_logged_in False def ensure_login(self): “””确保处于登录状态””” if self._check_cookie_valid(): self.is_logged_in True return # Cookie无效执行登录 self._perform_login() # 登录成功后保存新的Cookie self._save_cookies() self.is_logged_in True def _check_cookie_valid(self): “””检查当前Cookie是否有效””” try: # 先尝试加载已有Cookie self.driver.get(“https://your-test-site.com/”) if os.path.exists(self.cookie_file): # ... 加载Cookie代码 ... pass # 访问一个需要登录才能看到的页面或API self.driver.get(“https://your-test-site.com/api/user/profile”) # 检查响应或页面元素判断是否登录 # 例如页面包含用户信息或者API返回了用户数据而非401错误 # 这里简化处理检查某个登录后特有的元素 user_element self.driver.find_elements(By.ID, “user-avatar”) return len(user_element) 0 except Exception as e: print(f“检查登录状态时出错: {e}”) return False def _perform_login(self): “””执行完整的登录流程可能需要处理验证码””” self.driver.get(“https://your-test-site.com/login”) # … 输入用户名、密码、处理验证码 … # 点击登录按钮 # 等待登录成功跳转 WebDriverWait(self.driver, 10).until( EC.url_contains(“/dashboard”) ) def _save_cookies(self): “””保存当前有效的Cookie到文件””” cookies self.driver.get_cookies() with open(self.cookie_file, ‘w’) as f: json.dump(cookies, f) # 后续的测试方法在开始前调用 ensure_login def test_something(self): self.ensure_login() # … 具体的测试步骤 …场景三多账号Cookie隔离测试中可能需要切换不同角色的账号。可以为每个账号准备独立的Cookie文件或者使用不同的浏览器Profile用户数据目录。使用不同Profilefrom selenium import webdriver from selenium.webdriver.chrome.options import Options def create_driver_for_user(user_profile_dir): options Options() options.add_argument(f“--user-data-dir{user_profile_dir}”) # 可以指定Profile目录这样每个Driver实例有独立的Cookie、缓存等 driver webdriver.Chrome(optionsoptions) return driver # 为管理员和普通用户创建不同的驱动实例 admin_driver create_driver_for_user(“/path/to/admin_profile”) user_driver create_driver_for_user(“/path/to/user_profile”)3.4 高级话题处理HttpOnly、Secure Cookie与同源策略HttpOnly Cookie这种Cookie无法通过JavaScript包括Selenium的execute_script读取主要是为了防范XSS攻击。但Selenium WebDriver是通过浏览器调试协议操作的可以正常获取和添加HttpOnly Cookie。driver.get_cookies()返回的字典里httpOnly字段为True的就是这类Cookie。Secure Cookie仅在HTTPS连接时才会被发送。Selenium在访问HTTPS站点时可以正常处理Secure Cookie。如果你在本地测试HTTP环境可能需要让开发暂时关闭这个标志或者配置测试环境使用HTTPS。同源策略Cookie有domain和path属性限制。你不能给driver添加一个属于google.com的Cookie然后期望在访问baidu.com时携带它。添加Cookie前必须确保driver当前页面的域名与Cookie的domain匹配或符合其规则例如Cookie的domain是.example.com则可以用于a.example.com和b.example.com。4. 框架集成与最佳实践将验证码处理和Cookie管理融入到你的自动化测试框架中能让代码更清晰、更易维护。4.1 设计可配置的验证码处理模块一个好的验证码处理模块应该支持多种策略并且可以通过配置轻松切换。模块设计思路定义策略接口所有验证码处理方式都实现同一个接口比如CaptchaSolver包含一个solve(captcha_element)方法。实现具体策略DisableCaptchaSolver输入万能码、OcrCaptchaSolver、ThirdPartyPlatformSolver、ApiCaptchaSolver调用后端接口等。工厂模式选择根据配置文件如config.ini或环境变量决定实例化哪个策略。上下文注入将验证码处理器注入到需要它的页面对象Page Object或测试步骤中。简化的代码结构# captcha_solver.py from abc import ABC, abstractmethod import pytesseract from PIL import Image import requests class CaptchaSolver(ABC): abstractmethod def solve(self, driver, captcha_element): “””返回识别出的验证码文本””” pass class DisabledCaptchaSolver(CaptchaSolver): def __init__(self, universal_code“test”): self.universal_code universal_code def solve(self, driver, captcha_element): return self.universal_code # 直接返回万能码 class OcrCaptchaSolver(CaptchaSolver): def __init__(self, preprocessing_stepsNone): self.preprocessing preprocessing_steps or [] def solve(self, driver, captcha_element): # … 截图、预处理、OCR识别 … return recognized_text class ApiCaptchaSolver(CaptchaSolver): def __init__(self, api_url, auth_params): self.api_url api_url self.auth auth_params def solve(self, driver, captcha_element): # 从页面获取key调用接口 captcha_key captcha_element.get_attribute(“data-key”) response requests.get(self.api_url, params{‘key’: captcha_key}, authself.auth) return response.text # config.yaml 或 config.ini # captcha: # strategy: “api” # 可选: disabled, ocr, api, third_party # api_url: “http://test-env.internal/api/captcha” # universal_code: “000000” # 在框架初始化时 config load_config() if config[‘captcha’][‘strategy’] ‘api’: solver ApiCaptchaSolver(config[‘captcha’][‘api_url’], …) elif config[‘captcha’][‘strategy’] ‘disabled’: solver DisabledCaptchaSolver(config[‘captcha’][‘universal_code’]) # … 其他策略 … # 在登录页面对象中使用 class LoginPage: def __init__(self, driver, captcha_solver): self.driver driver self.solver captcha_solver self.captcha_input (By.ID, “captcha”) self.captcha_img (By.ID, “captcha-img”) def input_captcha(self): captcha_element self.driver.find_element(*self.captcha_img) code self.solver.solve(self.driver, captcha_element) self.driver.find_element(*self.captcha_input).send_keys(code)4.2 Cookie管理器的封装同样可以封装一个CookieManager类负责Cookie的加载、保存、验证和刷新。核心功能load(cookie_file): 从文件加载Cookie到当前driver。save(cookie_file): 将当前driver的Cookie保存到文件。is_valid(): 检查当前Cookie是否有效通过访问一个鉴权端点。refresh(): 如果无效执行重新登录流程并更新Cookie文件。将其与测试框架的setUp用例前和tearDown用例后钩子结合实现全局的登录态管理。4.3 稳定性与异常处理增强验证码处理的重试机制def solve_captcha_with_retry(solver, driver, element, max_retries3): for attempt in range(max_retries): try: code solver.solve(driver, element) # 输入验证码并提交后检查是否成功例如错误提示是否出现 # 这里假设有一个检查验证码是否正确的方法 if verify_captcha_success(driver): return code else: print(f“第{attempt1}次识别失败验证码错误。刷新重试...”) refresh_captcha(driver) # 刷新验证码图片 element driver.find_element(...) # 重新定位元素 except Exception as e: print(f“第{attempt1}次识别出现异常: {e}”) if attempt max_retries - 1: raise refresh_captcha(driver) raise Exception(“验证码识别重试次数用尽”)Cookie失效的优雅降级 在测试用例中如果关键操作因Cookie失效失败不应让整个用例崩溃而应记录错误、尝试重新登录并重试操作或者标记用例为“阻塞状态”。5. 常见问题排查与调试技巧在实际操作中你会遇到各种各样奇怪的问题。这里记录一些典型的坑和排查思路。5.1 验证码处理常见问题问题1OCR识别率始终很低。排查首先检查预处理后的图片。把预处理后保存的图片(captcha_processed.png)打开看看字符是否清晰可辨干扰线去除了吗如果人眼都难分辨机器识别率自然低。解决调整预处理参数二值化的阈值(threshold)、滤波器的尺寸和类型需要针对特定验证码样式调整。尝试不同OCR引擎和模式Tesseract有多个OCR引擎模式(--oem)和页面分割模式(--psm)。对于单行验证码--psm 7单行文本通常比默认模式好。也可以尝试其他OCR库如easyocr。放弃本地OCR如果验证码设计复杂果断转向第三方打码平台节省时间。问题2使用打码平台识别成功了但登录还是失败。排查验证码是否一次性有效有些验证码在一次识别失败即使识别正确或超时后就会失效。确保识别后立即输入并提交。网络延迟从截图、上传到获取结果有时间差验证码可能已过期。可以尝试在获取验证码图片元素后立即截图并发送减少延迟。输入错误打印出平台返回的识别结果确认没有多余空格或换行符。有些平台返回的结果可能包含干扰字符。解决在输入前对识别结果进行strip()处理。加入重试逻辑当登录失败提示“验证码错误”时刷新验证码重试。问题3滑动验证码滑动后提示“操作太快”或“验证失败”。排查轨迹太假。机器生成的匀速或简单加速减速轨迹容易被识别。解决引入随机性在轨迹生成函数中加入小的随机偏移量(random.uniform(-2, 2))模拟人手的不稳定。模拟人类犹豫在滑动开始前和结束后加入短暂的随机等待(time.sleep(random.uniform(0.1, 0.5)))。加入回拉人类操作有时会稍微过头再拉回来。可以在接近终点时加入一个很小的反向移动。使用更真实的轨迹算法搜索“Selenium模拟人类滑动轨迹”有一些开源算法模拟了更复杂的速度曲线。5.2 Cookie管理常见问题问题1add_cookie()失败报错“Invalid cookie domain”。原因这是最常见的问题。你尝试添加的Cookie的domain属性与浏览器当前页面的域名不匹配。解决在add_cookie之前必须先使用driver.get()访问一次该Cookie所属的域名或父域名。例如Cookie的domain是.example.com你需要先访问https://www.example.com或https://example.com。检查Cookie字典中的domain字段。从浏览器复制出来的Cookie其domain可能带有前导点如.example.com这表示对该域名及其所有子域名有效。确保你添加的domain值与浏览器中的一致。如果是从get_cookies()获取后直接保存再添加通常没问题。如果是手动构造Cookie字典要特别注意domain格式。问题2添加Cookie后刷新页面登录状态依然无效。排查Cookie是否关键确认你添加的Cookie包含了维持登录态的关键Cookie如sessionid,token。有时会有多个Cookie缺一不可。Cookie已过期检查Cookie字典中的expiry字段Unix时间戳。如果已经过期自然无效。在添加前可以判断一下。路径问题path属性限制了Cookie的有效路径。如果你添加的Cookie的path是/admin而你访问的是/user页面则该Cookie不会被发送。通常登录Cookie的path是/。Secure标志如果Cookie设置了secureTrue但当前页面是HTTP协议浏览器不会发送它。确保测试环境使用HTTPS或者让开发在测试环境关闭Secure标志。添加时机确保在添加Cookie后刷新了页面或导航到了新页面浏览器才会在请求中携带新的Cookie。仅仅添加不会立即生效。解决使用浏览器开发者工具的Application-Storage-Cookies面板对比手动登录后和脚本添加Cookie后该域名下的Cookie列表是否完全一致。这是最直接的调试方法。问题3从get_cookies()获取的Cookie列表里没有找到关键的session cookie。原因可能是HttpOnlyCookie在某种情况下获取不全或者该Cookie是Secure且当前连接不是HTTPS。更常见的原因是你获取Cookie的时机不对。必须在登录成功、页面完全加载后获取。解决在保存Cookie前确保已经跳转到了登录后的页面如仪表盘。可以加入一个显式等待等待登录后特有的元素出现再执行get_cookies()。5.3 通用调试技巧多用driver.get_cookies()和driver.current_url打印信息在关键步骤前后打印当前的Cookie和URL能帮你理清上下文。善用浏览器开发者工具Network面板查看登录请求和后续请求的Request Headers确认Cookie是否正确被携带。这是验证Cookie是否生效的金标准。Application面板实时查看和修改当前页面的Cookie可以手动修改值来测试或者对比脚本添加后的状态。截图辅助在验证码识别的前后、滑动验证码滑动前后使用driver.save_screenshot(‘debug_step1.png’)保存截图便于离线分析问题。降低执行速度在调试时在关键操作间加入time.sleep(2)让你有足够时间观察浏览器状态。当然正式脚本中应该用WebDriverWait代替sleep。处理验证码和Cookie是Web UI自动化从“玩具”走向“实用”的关键一步。没有一劳永逸的方案最好的策略是根据项目实际情况组合运用多种手段在测试环境优先寻求开发支持万能码或接口在不得已时使用可靠的第三方服务并将这些能力封装成框架的稳固组件。记住自动化测试的目的是提升效率而不是挑战安全机制。在合法合规的前提下找到那个平衡点你的自动化之路才会越走越顺。