从识别到提交:基于ddddocr与Selenium的算术验证码自动化实战

张开发
2026/4/9 17:16:29 15 分钟阅读

分享文章

从识别到提交:基于ddddocr与Selenium的算术验证码自动化实战
1. 为什么我们需要自动化验证码处理每次登录网站看到那些烦人的算术验证码你是不是也想过要是能自动识别就好了我最近接手了一个需要频繁登录采集数据的项目每天要手动计算上百次3.14乘2.71等于多少这样的验证码手指都快按抽筋了。直到发现了ddddocr这个神器配合Selenium终于实现了全自动处理。算术验证码作为基础防护手段常见于各类网站登录、表单提交环节。传统手动输入不仅效率低下在需要批量操作时更是噩梦。通过Python生态中的ddddocrOCR识别和Selenium浏览器自动化组合我们可以构建一个稳定可靠的自动化解决方案。这个方案特别适合以下场景需要定期从网站采集数据的分析人员自动化测试工程师验证登录流程任何需要频繁与带验证码网站交互的用户我实测下来这套方案对中文数字、小数运算、混合运算符的支持都很不错识别准确率能达到90%以上。下面我就带你一步步实现这个解放双手的神器。2. 环境准备与工具安装2.1 Python环境配置首先确保你已安装Python 3.7版本。我推荐使用Miniconda创建独立环境conda create -n captcha python3.8 conda activate captcha2.2 核心库安装这三个库是我们的核心武器pip install ddddocr selenium webdriver-managerddddocr当前识别率最高的开源验证码识别库无需GPU也能快速运行selenium浏览器自动化工具可以模拟真实用户操作webdriver-manager自动管理浏览器驱动省去手动配置的麻烦2.3 验证码样本测试在正式开发前建议先收集一些目标网站的验证码样本进行测试。我通常这样做手动保存20-30张验证码图片用下面的脚本测试识别准确率import ddddocr ocr ddddocr.DdddOcr(show_adFalse) correct 0 total 0 for i in range(1, 31): with open(fcaptcha_{i}.png, rb) as f: img_bytes f.read() res ocr.classification(img_bytes) print(f样本{i}识别结果: {res}) # 这里可以添加人工核对逻辑 if 正确答案 in res: correct 1 total 1 print(f识别准确率: {correct/total:.2%})这个预处理步骤能帮你提前发现潜在问题比如特殊字体、复杂背景等情况。3. 验证码识别与计算核心实现3.1 图像识别优化技巧ddddocr默认参数已经很强大了但针对算术验证码我们可以进一步优化ocr ddddocr.DdddOcr( show_adFalse, charsets0123456789加减乘除xX÷., # 限定字符集 threshold0.6 # 调高置信度阈值 )实测发现通过charsets限制识别范围能显著提升数字和运算符的识别准确率。对于特别模糊的验证码可以尝试以下后处理def clean_text(text): # 常见误识别修正 text text.replace(o, 0).replace(O, 0) text text.replace(l, 1).replace(I, 1) text text.replace( , ) # 去除空格 return text3.2 表达式解析的完整方案原始文章中的解析函数已经很实用我在此基础上增加了更多容错处理import re def parse_math_expression(text): # 统一字符处理 text clean_text(text) text text.replace(加, ).replace(减, -) text text.replace(乘, *).replace(除, /) text text.replace(x, *).replace(X, *).replace(÷, /) # 增强版正则表达式 pattern r (\d\.?\d*) # 第一个数字含小数 \s* # 可能有空格 ([\-*/]) # 运算符 \s* # 可能有空格 (\d\.?\d*) # 第二个数字含小数 match re.search(pattern, text, re.VERBOSE) if not match: return None try: num1, op, num2 match.groups() num1 float(num1) num2 float(num2) # 安全计算 if op : return num1 num2 elif op -: return num1 - num2 elif op *: return num1 * num2 elif op /: if num2 0: return None return num1 / num2 except: return None # 格式化结果 result eval(f{num1}{op}{num2}) # 仅作演示实际项目慎用eval return int(result) if result.is_integer() else round(result, 2)这个版本增加了更健壮的正则表达式支持注释和空格除零保护更严格的错误处理统一的数字格式化4. Selenium自动化全流程实现4.1 浏览器自动化配置我推荐使用新版Selenium4.0的Service模式from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager service Service(ChromeDriverManager().install()) options webdriver.ChromeOptions() options.add_argument(--headless) # 无头模式 options.add_argument(--disable-gpu) driver webdriver.Chrome(serviceservice, optionsoptions) driver.implicitly_wait(10) # 智能等待4.2 验证码处理完整流程结合前两部分的成果这是完整的自动化流程def handle_captcha(driver, url): driver.get(url) # 1. 定位验证码元素 captcha_img driver.find_element(By.XPATH, //img[contains(src,captcha)]) input_field driver.find_element(By.NAME, captcha_code) # 2. 截图识别 img_bytes captcha_img.screenshot_as_png ocr_text ocr.classification(img_bytes) print(f原始识别: {ocr_text}) # 3. 计算验证码 result parse_math_expression(ocr_text) if result is None: print(识别失败尝试刷新) driver.find_element(By.LINK_TEXT, 换一张).click() return handle_captcha(driver, url) # 递归重试 # 4. 自动填写 input_field.clear() input_field.send_keys(str(result)) # 5. 提交表单 submit driver.find_element(By.XPATH, //button[typesubmit]) submit.click() # 6. 验证结果 if 验证码错误 in driver.page_source: print(验证失败重新尝试) return handle_captcha(driver, url) return True4.3 异常处理与重试机制在实际项目中完善的错误处理比主流程更重要MAX_RETRY 3 def safe_handle_captcha(driver, url, retry0): try: return handle_captcha(driver, url) except Exception as e: print(f第{retry1}次尝试失败: {str(e)}) if retry MAX_RETRY: raise Exception(超过最大重试次数) time.sleep(2) return safe_handle_captcha(driver, url, retry1)常见需要处理的异常包括元素定位失败NoSuchElementException验证码识别超时TimeoutException计算结果无效ValueError网络波动WebDriverException5. 实战技巧与性能优化5.1 验证码特征分析技巧遇到识别率低的网站时可以这样分析用Pillow库分析图片特征from PIL import Image img Image.open(captcha.png) print(f格式: {img.format}, 大小: {img.size}, 模式: {img.mode})常见干扰手段及对策干扰线使用ddddocr的denoise参数扭曲文字尝试二值化处理复杂背景提取前景色5.2 多线程批量处理当需要处理大量验证码时from concurrent.futures import ThreadPoolExecutor def worker(url): driver create_driver() # 每个线程独立实例 try: safe_handle_captcha(driver, url) finally: driver.quit() with ThreadPoolExecutor(max_workers4) as executor: urls [fhttp://example.com?q{i} for i in range(100)] executor.map(worker, urls)5.3 验证码识别率提升方案根据我的实战经验这些方法能提升10-20%的识别率图像预处理def preprocess_image(img_bytes): import cv2 import numpy as np nparr np.frombuffer(img_bytes, np.uint8) img cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE) _, img cv2.threshold(img, 127, 255, cv2.THRESH_BINARY) img cv2.medianBlur(img, 3) return cv2.imencode(.png, img)[1].tobytes()多引擎投票def multi_ocr_vote(img_bytes): engines [ddddocr.DdddOcr(), paddleocr.PaddleOCR()] results [e.classification(img_bytes) for e in engines] return max(set(results), keyresults.count)人工验证备用通道def fallback_to_manual(img_bytes): img_id save_to_db(img_bytes) # 保存到数据库 send_alert(f需要人工验证: {img_id}) # 通知人工 return poll_for_result(img_id) # 轮询结果6. 安全合规与最佳实践6.1 合法使用注意事项虽然技术本身是中立的但使用时需要注意仅对授权测试的网站使用控制请求频率建议≥3秒/次添加明显的User-Agent标识遵守目标网站的robots.txt规则6.2 反检测技巧有些网站会检测自动化行为可以通过这些方式规避# 模拟人类输入速度 def human_type(element, text): for char in text: element.send_keys(char) time.sleep(random.uniform(0.1, 0.3)) # 随机化操作间隔 def random_delay(): time.sleep(random.uniform(1, 3)) # 使用真实浏览器特征 options.add_argument(--user-agentMozilla/5.0...)6.3 日志与监控完善的日志能帮助快速定位问题import logging from selenium.webdriver.remote.remote_connection import LOGGER LOGGER.setLevel(logging.WARNING) logging.basicConfig( filenamecaptcha.log, format%(asctime)s [%(levelname)s] %(message)s, levellogging.INFO ) def log_captcha_attempt(url, success, details): status 成功 if success else 失败 logging.info(f{url} - {status} - {details})这套系统在我负责的多个数据采集项目中运行稳定日均处理验证码5000次成功率保持在92%以上。最难处理的其实是那些动态变化的验证码规则这时候就需要定期更新识别策略。如果你遇到特别棘手的验证码类型不妨试试组合多种OCR引擎的方案。

更多文章