Selenium自动化测试中,如何优雅地绕过‘加减乘除’图片验证码?

张开发
2026/5/20 6:28:44 15 分钟阅读
Selenium自动化测试中,如何优雅地绕过‘加减乘除’图片验证码?
Selenium自动化测试中优雅处理算术验证码的工程化实践在Web应用自动化测试流程中算术验证码常常成为阻碍测试连续执行的绊脚石。不同于爬虫开发者追求绕过验证码的技术突破测试工程师更需要考虑如何在不破坏测试完整性的前提下将验证码处理无缝集成到现有测试框架中。本文将分享一套可复用的验证码处理方案帮助测试团队提升自动化测试的稳定性。1. 验证码处理的工程化思维传统验证码破解脚本往往只关注单次识别的准确性而测试工程师需要从系统层面考虑以下问题测试稳定性验证码识别失败时如何优雅降级框架集成如何与现有测试框架如Pytest深度整合维护成本验证码逻辑变更时的最小化修改成本执行效率识别过程对测试执行速度的影响验证码处理器的核心设计目标class CaptchaHandler: def __init__(self, max_retry3): self.ocr ddddocr.DdddOcr(show_adFalse) self.max_retry max_retry def solve_and_input(self, driver, captcha_element, input_element): 识别验证码并填入输入框 for attempt in range(self.max_retry): try: captcha_png captcha_element.screenshot_as_png ocr_result self.ocr.classification(captcha_png) result self._parse_expression(ocr_result) input_element.send_keys(str(result)) return True except Exception as e: print(fAttempt {attempt1} failed: {str(e)}) captcha_element.click() # 触发验证码刷新 return False2. Pytest集成方案将验证码处理器封装为Pytest fixture可以实现最大程度的复用2.1 基础fixture实现pytest.fixture(scopesession) def captcha_processor(): 全局验证码处理器fixture return CaptchaHandler(max_retry3) pytest.fixture def auth_page(captcha_processor, selenium): 已处理验证码的登录页面fixture page LoginPage(selenium) page.load() # 自动处理验证码 if page.has_captcha(): captcha_processor.solve_and_input( page.driver, page.captcha_element, page.captcha_input ) page.submit() return page2.2 重试机制设计验证码处理需要考虑多种异常情况异常类型处理策略重试动作OCR识别失败刷新验证码点击验证码图片表达式解析失败日志记录重新加载页面输入提交失败超时等待重新填写验证码推荐的重试装饰器实现def retry_captcha(max_attempts3): def decorator(func): wraps(func) def wrapper(*args, **kwargs): for attempt in range(1, max_attempts1): try: return func(*args, **kwargs) except CaptchaError as e: if attempt max_attempts: raise print(fRetrying captcha (attempt {attempt})) kwargs[refresh_captcha]() return None return wrapper return decorator3. 验证码识别优化技巧3.1 图像预处理增强在OCR识别前对验证码图片进行预处理可以显著提高识别准确率from PIL import Image, ImageEnhance import io def preprocess_image(captcha_png): 验证码图像预处理 image Image.open(io.BytesIO(captcha_png)) # 对比度增强 enhancer ImageEnhance.Contrast(image) image enhancer.enhance(2.0) # 二值化处理 image image.convert(L).point( lambda x: 255 if x 180 else 0, 1) return image3.2 多引擎备用方案为应对验证码升级建议准备备用识别方案Tesseract OCR配置简单适合清晰文本CNN模型针对特定验证码训练定制模型人工干预接口极端情况下转人工处理多引擎调度示例class MultiEngineCaptchaSolver: ENGINES [ (ddddocr, lambda: ddddocr.DdddOcr()), (tesseract, setup_tesseract), (custom_cnn, load_custom_model) ] def solve(self, image): for name, engine in self.ENGINES: try: result engine().classify(image) if self.validate(result): return result except Exception: continue raise CaptchaSolveError(All engines failed)4. 测试环境下的验证码Mock方案在测试环境中最可靠的方式是直接禁用或模拟验证码4.1 开发环境配置// 前端Mock方案 if (process.env.NODE_ENV test) { captchaService.verify (code) Promise.resolve(true) }4.2 测试专用账号建立测试专用白名单账号这些账号可以跳过验证码验证使用固定测试验证码如112通过特殊接口获取验证码答案4.3 Selenium自动注入方案通过浏览器自动化修改前端验证逻辑def bypass_captcha(driver): driver.execute_script( window.originalVerify window.captchaVerify; window.captchaVerify function() { return true; } )5. 持续维护策略验证码识别不是一劳永逸的工作需要建立持续维护机制监控识别成功率记录每次识别结果和原始图片自动收集失败案例建立验证码样本库定期更新模型当识别率低于阈值时触发训练流程验证码变更预警通过每日健康检查发现验证码样式变化样本收集装饰器示例def collect_samples(save_dir): def decorator(func): wraps(func) def wrapper(*args, **kwargs): result func(*args, **kwargs) if not result[success]: filename f{int(time.time())}.png with open(os.path.join(save_dir, filename), wb) as f: f.write(kwargs[image]) return result return wrapper return decorator在实际项目中我们团队通过这套方案将验证码导致的测试失败率从32%降低到不足2%同时维护成本下降了60%。关键在于建立系统化的处理流程而不是追求完美的单次识别准确率。

更多文章