当前位置: 首页 > java >正文

算术图片验证码(四则运算)+selenium

一、表达式解析

这里假设已经识别出来表达式,如何识别验证码图片里的表达式,放在下面讲。涉及到的正则表达式的解析放在本篇文章最后面。


import re
# 表达式解析(支持小数的 +-*/ 和中文运算符)
def parse_math_expression(text):# 替换中文运算符为英文text = text.replace('加', '+').replace('减', '-').replace('乘', '*').replace('除', '/')text = text.replace('x', '*').replace('X', '*').replace('÷', '/')# 正则表达式提取表达式中的数字和运算符# match = re.search(r'(\d+)\s*([+\-*/]|加|减|乘|除)\s*(\d+)', text)match = re.search(r'(\d+(?:\.\d+)?)\s*([+\-*/]|加|减|乘|除)\s*(\d+(?:\.\d+)?)', text) # 可匹配小数if not match:return Nonenum1, operator, num2 = match.groups()try:num1 = float(num1)num2 = float(num2)# 计算结果if operator == '+':result = num1 + num2elif operator == '-':result = num1 - num2elif operator == '*':result = num1 * num2elif operator == '/':result = num1 / num2else:return None# 要么返回整数,要么返回最多两位小数,round()四舍六入五平分,如果五平分的进位不对,刷新页面重新识别吧,懒得处理了return int(result) if result.is_integer() else round(result, 2)except:return None# 调试用
ocr_result = "9.1加3.2等于"result = parse_math_expression(ocr_result)
if result is not None:print(f"计算结果: {result}")else:print("无法解析表达式")

二、配合selenium

#!/usr/bin/env python
# encoding: utf-8from selenium import webdriver
from selenium.webdriver.common.by import By
import time
import ddddocr
import re# 表达式解析(支持 +-*/ 和中文运算符)
def parse_math_expression(text):# 替换中文运算符为英文text = text.replace('加', '+').replace('减', '-').replace('乘', '*').replace('除', '/')text = text.replace('x', '*').replace('X', '*').replace('÷', '/')# 正则表达式提取表达式中的数字和运算符# match 对象包含匹配成功的信息,若未匹配到则返回 None# match = re.search(r'(\d+)\s*([+\-*/]|加|减|乘|除)\s*(\d+)', text) #匹配整数match = re.search(r'(\d+(?:\.\d+)?)\s*([+\-*/]|加|减|乘|除)\s*(\d+(?:\.\d+)?)', text) # 可匹配小数if not match:return Nonenum1, operator, num2 = match.groups() #groups()	仅包含捕获组,索引从 0 开始,如('3.14', '乘', '2.71')try:num1 = float(num1)num2 = float(num2)# 计算结果if operator == '+':result = num1 + num2elif operator == '-':result = num1 - num2elif operator == '*':result = num1 * num2elif operator == '/':result = num1 / num2else:return None# 要么返回整数,要么返回最多两位小数,round()四舍六入五平分,如果五平分的进位不对,刷新页面重新识别吧return int(result) if result.is_integer() else round(result, 2)except:return None# 配置浏览器
options = webdriver.ChromeOptions()
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(5)# 打开验证码页面
driver.get('http://127.0.0.1/1.html')
time.sleep(2)  # 等待页面加载# 获取验证码图片
captcha_element = driver.find_element(By.ID, 'captcha')
captcha_png = captcha_element.screenshot_as_png# 初始化 OCR 引擎(支持中文运算符)
ocr = ddddocr.DdddOcr(show_ad=False)
# OCR 识别
ocr_result = ocr.classification(captcha_png)
print(f"OCR 识别结果: {ocr_result}")# 计算表达式结果
# ocr_result = '9.14加3.15等于' # debug使用
result = parse_math_expression(ocr_result)if result is not None:print(f"计算结果: {result}")# 自动填写结果(假设输入框 ID 为 'captcha_input')input_element = driver.find_element(By.ID, 'captcha_input')input_element.send_keys(str(result))# 提交表单(假设按钮 ID 为 'submit')submit_button = driver.find_element(By.ID, 'submit')submit_button.click()print("已提交表单")
else:print("无法解析表达式")# 等待用户查看结果后关闭浏览器
time.sleep(5)
driver.quit()

三、引申:正则表达式搭配group()

group() 是 Python 正则表达式模块 re 中用于提取匹配结果的核心方法,必须与正则表达式的匹配对象(Match 对象)搭配使用。

1. group()基本定义

  • match.group(n):返回正则表达式中第 n 个捕获组的匹配内容。
  • match.group(0):返回整个匹配的字符串(即正则表达式匹配到的完整文本)。
import retext = "今天是2023-06-07"
regex = r'(\d{4})-(\d{2})-(\d{2})'  # 三个捕获组:年、月、日
match = re.search(regex, text)if match:print(match.group(0))  # 整个匹配: "2023-06-07"print(match.group(1))  # 第一个捕获组: "2023"print(match.group(2))  # 第二个捕获组: "06"print(match.group(3))  # 第三个捕获组: "07"

注意:match.groups()跟match.group()是不一样的,groups()返回内容仅包含捕获组(即括号()中定义的内容),不包含整个匹配结果。上面的算术代码用的是groups()。

2. 例子中的正则表达式解析

(1)(\d+(?:.\d+)?) 匹配整数或小数

部分含义示例匹配
\.匹配小数点(. 需要转义).
\d+匹配 1 个或多个数字14、5
(?:...)非捕获组(不创建分组)仅用于分组,不保存结果
?前面的内容可选(0 次或 1 次).14、空字符串

(2)空白字符 \s*

  • \s:匹配任意空白字符(空格、制表符、换行等)
  • *:匹配 0 次或多次(即可有可无)

(3)运算符部分 ([+-*/]|加|减|乘|除)

  • 逻辑或 |:分隔多个可选模式,匹配其中任意一个
  • 分组 ():捕获匹配的内容,便于后续提取 [ ] :字符组,匹配其中任意一个字符
  • 需要转义(-),否则表示范围(如 [0-9])
  • +、* 理论上需要转义,但多数引擎允许不转义

四、用到的验证码识别库ddddocr

DdddOcr 带带弟弟OCR通用验证码离线本地识别SDK免费开源版
(链接包含各种强大用法的使用文档,感兴趣可看,如下图)
在这里插入图片描述

http://www.xdnf.cn/news/12645.html

相关文章:

  • 【大模型】大模型RAG(Retrieval-Augmented Generation)面试题合集
  • 欢乐熊大话蓝牙知识16:蓝牙是怎么找设备的?扫描与广播的“对话内幕”
  • Shell编程精髓:表达式与数组实战指南
  • DbServer链接KingBase8(人大)数据库
  • Android座舱系统Agent改造方案
  • day 47
  • 微前端架构下的B端页面设计:模块化与跨团队协作的终极方案
  • Python爬虫-爬取各省份各年份高考分数线数据,进行数据分析
  • 国产pcie switch,支持PCIE 3.0/4.0/5.0,支持昇腾310/910 GPU,支持龙芯、海光、飞腾
  • 小白成长之路-Linux Shell脚本练习
  • 2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版
  • Xilinx IP 解析之 Block Memory Generator v8.4 ——01-手册重点解读(仅 Native R
  • 前端开发面试题总结-JavaScript篇(二)
  • .Net Framework 4/C# 泛型的使用、迭代器和分部类
  • 本地windows服务器部署私有云网盘Nextcloud并无公网IP实现外部访问
  • 多线程中的泛型应用深度解析:类型安全与并发编程的完美融合
  • Java方法引用深度解析:从匿名内部类到函数式编程的演进
  • 算法训练第十天
  • 分享5个免费5个在线工具网站:Docsmall、UIED Tool在线工具箱、草料二维码、图片在线压缩、表情符号
  • 【嵌入式设备】使用PICO7抓取CH341A读写EEPROM的IIC波形
  • 视频字幕质量评估的大规模细粒度基准
  • 使用cd4060倒计时控制继电器,防止摩托车漏电
  • day 27 装饰器函数
  • SQL进阶之旅 Day 20:锁与并发控制技巧
  • C#:发送一封带有附件的邮件
  • Android实现点击Notification通知栏,跳转指定activity页面
  • 华为云Flexus+DeepSeek征文|体验华为云ModelArts快速搭建Dify-LLM应用开发平台并创建自己的自定义聊天助手
  • MATLAB-电偶极子所产出的电磁场仿真
  • 黑马点评【基于redis实现共享session登录】
  • 六、Sqoop 导出