Python+Selenium+Pytesseract实现图片验证码识别
作者:Python可乐呀 发布时间:2023-08-17 11:44:01
标签:Python,验证码,识别
一、selenium截取验证码
import json
from io import BytesIO
import time
from test.testBefore.testDriver import driver
from test.util.test_pytesseract import recognize
from PIL import Image
import allure
import unittest
'''
/处理验证码
'''
# 要截图的元素
element = driver.find_element_by_xpath('//*[@id="imgVerifyCode"]')
# 坐标
x, y = element.location.values()
# 宽高
h, w = element.size.values()
# 把截图以二进制形式的数据返回
image_data = driver.get_screenshot_as_png()
# 以新图片打开返回的数据
screenshot = Image.open(BytesIO(image_data))
# 对截图进行裁剪
result = screenshot.crop((x, y, x + w, y + h))
# 显示图片
# result.show()
# 保存验证码图片
result.save('VerifyCode.png')
# 调用recognize方法识别验证码
code = recognize('VerifyCode.png')
# 输入验证码
driver.find_element_by_xpath('//*[@id="txtcode"]').send_keys(code)
'''
处理验证码/
'''
注意:driver是引用我自己写的文件,可以自己随便写一个。识别图片的代码单独放在util文件夹下面的,参考标题三的代码,需要时引用。以上代码定位元素都需要根据自己的项目定位元素修改。
二、安装识别环境pytesseract+Tesseract-OCR
如果没有输出,又不确定你的pytesseract环境是否安装好,可以用一张没有干扰的图片识别看看能不能有输出结果,以下样例在我的环境中可以直接输出识别结果8fnp
验证识别环境是否正常
直接使用pytesseract识别图片
001.png
text = pytesseract.image_to_string('./001.png')
print(text)
三、处理验证码图片
直接截图的验证码图片存在噪点或者干扰线等,直接使用pytesseract识别可能会没有输出结果,如果环境正常,但没有输出结果,那多半是因为图片没有处理好,识别不出来,可以多尝试一些处理图片的方式,以下代码处理我截图这种类似的图片效果比较好。
图片处理识别
对图片处理的过程:
图片处理过程中可以多用im.show()看看每一步处理后的图片是不是符合预期,如果效果不好调一下参数。另外在学习过程中发现有童鞋说识别不出来把图片使用cv2.resize()这个方法放大就能识别,可以参考Python中图像的缩放 resize()函数的应用
实际截取的图片
处理后的图片
test_pytesseract.py
import pytesseract
from fnmatch import fnmatch
import cv2
import os
def clear_border(img, img_name):
'''
去除边框
'''
h, w = img.shape[:2]
for y in range(0, w):
for x in range(0, h):
# if y ==0 or y == w -1 or y == w - 2:
if y < 2 or y > w - 2:
img[x, y] = 255
# if x == 0 or x == h - 1 or x == h - 2:
if x < 1 or x > h - 1:
img[x, y] = 255
return img
def interference_line(img, img_name):
'''
干扰线降噪
'''
h, w = img.shape[:2]
# !!!opencv矩阵点是反的
# img[1,2] 1:图片的高度,2:图片的宽度
for r in range(0, 2):
for y in range(1, w - 1):
for x in range(1, h - 1):
count = 0
if img[x, y - 1] > 245:
count = count + 1
if img[x, y + 1] > 245:
count = count + 1
if img[x - 1, y] > 245:
count = count + 1
if img[x + 1, y] > 245:
count = count + 1
if count > 2:
img[x, y] = 255
return img
def interference_point(img, img_name, x=0, y=0):
"""点降噪
9邻域框,以当前点为中心的田字框,黑点个数
:param x:
:param y:
:return:
"""
# todo 判断图片的长宽度下限
cur_pixel = img[x, y] # 当前像素点的值
height, width = img.shape[:2]
for y in range(0, width - 1):
for x in range(0, height - 1):
if y == 0: # 第一行
if x == 0: # 左上顶点,4邻域
# 中心点旁边3个点
sum = int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 2 * 245:
img[x, y] = 0
elif x == height - 1: # 右上顶点
sum = int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1])
if sum <= 2 * 245:
img[x, y] = 0
else: # 最上非顶点,6邻域
sum = int(img[x - 1, y]) \
+ int(img[x - 1, y + 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
elif y == width - 1: # 最下面一行
if x == 0: # 左下顶点
# 中心点旁边3个点
sum = int(cur_pixel) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x, y - 1])
if sum <= 2 * 245:
img[x, y] = 0
elif x == height - 1: # 右下顶点
sum = int(cur_pixel) \
+ int(img[x, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y - 1])
if sum <= 2 * 245:
img[x, y] = 0
else: # 最下非顶点,6邻域
sum = int(cur_pixel) \
+ int(img[x - 1, y]) \
+ int(img[x + 1, y]) \
+ int(img[x, y - 1]) \
+ int(img[x - 1, y - 1]) \
+ int(img[x + 1, y - 1])
if sum <= 3 * 245:
img[x, y] = 0
else: # y不在边界
if x == 0: # 左边非顶点
sum = int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
elif x == height - 1: # 右边非顶点
sum = int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x - 1, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1])
if sum <= 3 * 245:
img[x, y] = 0
else: # 具备9领域条件的
sum = int(img[x - 1, y - 1]) \
+ int(img[x - 1, y]) \
+ int(img[x - 1, y + 1]) \
+ int(img[x, y - 1]) \
+ int(cur_pixel) \
+ int(img[x, y + 1]) \
+ int(img[x + 1, y - 1]) \
+ int(img[x + 1, y]) \
+ int(img[x + 1, y + 1])
if sum <= 4 * 245:
img[x, y] = 0
return img
def _get_dynamic_binary_image(filedir, img_name):
'''
自适应阀值二值化
'''
filename = './' + img_name.split('.')[0] + '-binary.png'
img_name = filedir + '/' + filename
im = cv2.imread(img_name)
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
th1 = cv2.adaptiveThreshold(im, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 21, 1)
return th1
def recognize(image):
filedir = './' # 验证码路径
for file in os.listdir(filedir):
if fnmatch(file, image):
img_name = file
# 自适应阈值二值化
im = _get_dynamic_binary_image(filedir, img_name)
# # 去除边框
im = clear_border(im, img_name)
# 对图片进行干扰线降噪
im = interference_line(im, img_name)
# 对图片进行点降噪
im = interference_point(im, img_name)
filename = './' + img_name.split('.')[0] + '-interferencePoint.png' # easy_code为保存路径
cv2.imwrite(filename, im) # 保存图片
text = pytesseract.image_to_string(im, lang="eng",
config='--psm 6 digits') # config=digits只识别数字
return text
'''
--psm 参数含义
0:定向脚本监测(OSD)
1: 使用OSD自动分页
2 :自动分页,但是不使用OSD或OCR(Optical Character Recognition,光学字符识别)
3 :全自动分页,但是没有使用OSD(默认)
4 :假设可变大小的一个文本列。
5 :假设垂直对齐文本的单个统一块。
6 :假设一个统一的文本块。
7 :将图像视为单个文本行。
8 :将图像视为单个词。
9 :将图像视为圆中的单个词。
10 :将图像视为单个字符。
'''
来源:https://www.cnblogs.com/sn520/p/15777998.html
0
投稿
猜你喜欢
- 本文实例讲述了Python实现监控键盘鼠标操作。分享给大家供大家参考,具体如下:# -*- coding: utf-8 -*-import
- 判断函数如下:Public Function CheckBIG(strSource As String) As BooleanDim idx
- 1、引言续上一篇《一行代码,导入Python所有库》不知道是不是都跟小鱼一样,把剩下的时间来学(撩)习(妹)。为了体现小鱼在懒上的造就,小鱼
- 想买mate40,但总是抢不到,所以想试着能不能写个脚本代码。第一步:把想要抢购的商品加进购物车,注意:脚本是对购物车内全部商品进行下单操作
- 听到一些人说现在做产品设计很没有成就感。没有什么创造力,除了抄袭模仿(称之为竞争分析)、千篇一律(又称规范标准)还有复杂的流程、粗制滥造的表
- 本文实例为大家分享了PHP实现统计代码行数小工具,供大家参考,具体内容如下为了方面统计编程代码行数,做了一个小工具。自动统计指定目录以及目录
- 关于matplotlib如何设置图例的位置?如何将图例放在图外?以及如何在一幅图有多个子图的情况下,删除重复的图例?我用一个简单的例子说明一
- 任何熟悉SQL和关系数据库的人都遇见过大量的连接类型。最简单的说,连接(join)会把两个表的内容组合到一个虚拟表或者recordset内。
- 一、logging模块Python中有一个模块logging,可以直接记录日志# 日志级别# CRITICAL 50# ERRO
- 今天在推上看到一条获取PHP类私有属性的推文,感觉很有意思:顺着推文联想,还有其他方式吗?经过自己的测试及网上答案,总结出三种方法:1. 反
- 看到Django和layim实现websocketde资料很少,自己就琢磨了下,顺便搭建出来了。自己要去找闲心大神授权呀。先来看图这是初次搭
- isset($var); //为false 没有定义没有定义为假 $var = ''
- 核心代码function convert2utf8($string) { return iconv(&
- 我们都知道在9i之前,要想获得建表和索引的语句是一件很麻烦的事。我们通常的做法都是通过export with rows=no来得到,但它的输
- ASP 本身不支持动态包含文件,现在的动态包含是通过 FSO 把被包含的文件合并到主文件里再运行。以下也有把形如 <!--#
- 我们今天就来看一下PHP 7正式版的算法和 wordpress 应用在其上的性能表现。PHP7 的安装,真是非常地向下兼容,下载,解压,把之
- 在我们处理文件的时候,会遇到这样的一种场景,我们需要对某个文件进行操作,然后生成与原文件名相同的文件(只是文件格式改变)。那么这个时候就可以
- python __init__.py 和 __all__作用一、__init__.py1、导入文件夹包的时候,会运行写在该文件夹包下的__i
- 可以使用numpy中的linspace函数np.linspace(start, stop, num, endpoint, retstep,
- 本文实例讲述了Python 多线程,threading模块,创建子线程的两种方式。分享给大家供大家参考,具体如下:GIL(全局解释器锁)是C