工作中遇到的需要破解算数验证码的情况
如图:
刚开始 想到的是 切割识别,但是,识别成功率太低了,就放弃了。
然后看到了一篇知乎文章,原文链接:python爬虫验证码识别 (手把手教会你验证码识别)opencv图像处理 图片处理 验证码处理 降噪 简单易懂验证码处理 - 知乎
借鉴了里面的方法。
我遇到的验证码都是来自此处:https://cmegsb.cma.org.cn/national_project/CheckCodeImageServlet
第一步:先批量下载图片保存至本地文件夹
def getImg():
i = 0
while i < 10:
html = requests.get('https://cmegsb.cma.org.cn/national_project/CheckCodeImageServlet', verify=False)
image = Image.open(BytesIO(html.content))
image.save('img_test/%s.jpg' % i)
i += 1
print(i)
第二步:先安装 pip install muggle_ocr 可能会提示下载失败,
可以:pip install -i https://pypi.douban.com/simple/ muggle_ocr(参考:pip install muggle_ocr 失败,解决办法_lsf_007的博客-CSDN博客)
def begin():
# 图片链接路径
path = r"D:\img_test"
import muggle_ocr
sdk = muggle_ocr.SDK(model_type=muggle_ocr.ModelType.OCR)
threshold_values = [115, 150, 127, 90, 120, 130, 135, 145, 155, 160, 180]
for threshold in threshold_values:
total = len(os.listdir(path))
errorCount = 0
for index, i in enumerate(os.listdir(path)):
right_str = i.split("_")[0]
print('%s / %s' % (index + 1, total), i + "->" + right_str)
yzm = cv2.imread(path + '\\' + i) # 读图片
yzm = cv2.cvtColor(yzm, cv2.COLOR_BGR2GRAY) # cv2 方法灰度化
# 二值化
thresh, yzm = cv2.threshold(yzm, threshold, 255, cv2.THRESH_BINARY)
# yzm:表示需要操作的数组
# threshold:表示阈值 (根据验证码图片特性 可选值:90、115、120、127、130、135、150、155、160、180)、常用【115、150、127】--- 这些都是我一个一个的测试出来的
# 255 表示最大值
# 降噪
yzm = cv2.morphologyEx(yzm, cv2.MORPH_CLOSE, np.ones(shape=(1, 1)))
# 保存灰度化的图片
cv2.imwrite('new_img.png', yzm)
img = open('new_img.png', 'rb').read()
text = sdk.predict(image_bytes=img)
if ('乘' in text or '减' in text or '加' in text) and (str(text).replace(' ', '').endswith('=?')):
# 判断是否为 正常值
b = text.replace('=', '').replace('?', '')
a = b.split('乘') if '乘' in text else b.split('加') if '加' in text else b.split('减')
a1 = a[0]
a2 = a[1]
try:
a1 = int(a1)
a2 = int(a2)
print('%s / %s' % (index + 1, total), threshold, ' 正常code: ', text)
print(a1, a2, type(a1), type(a2))
_id = hashlib.md5(str(datetime.datetime.now()).encode('utf-8')).hexdigest()
try:
# 用 a、b 代替 =、?
new_path = './img_save/%s_%s.png' % (text.replace('?', 'b').replace('=', 'a'), _id)
os.rename(path + '\\' + i, new_path)
try:
os.remove(path + '\\' + i)
except:
pass
except Exception as e:
errorCount += 1
except:
errorCount += 1
else:
errorCount += 1
print('运行结束:threshold: %s 共 %s 个, 成功:%s , 失败:%s' % (threshold, total, total - errorCount, errorCount))
用 muggle_ocr 去识别(识别率 55%左右,比较低),
所以,我就用此识别,筛选出有效的 验证码,然后打标记,作为训练集。
最后,强烈推荐一款开源的训练框架: https://github.com/kerlomz/captcha_trainer
用此训练过之后,识别率达到了 95%以上。
识别效果: