主要工具:
1、tesseract-ocr-w64-setup-v4.0 需要安装
地址:https://digi.bib.uni-mannheim.de/tesseract/
安装完成需配置环境变量:
PATH中增加:C:\Program Files (x86)\Tesseract-OCR
增加TESSDATA_PREFIX变量:C:\Program Files (x86)\Tesseract-OCR\tessdata
2、jTessBoxEditorFX(需安装JDK1.8)
地址:https://sourceforge.net/projects/vietocr/
jTessBoxEditorFX操作:可通过工具栏,对识别不到位的区域进行整合、切割、插入、删除、调整坐标等。
主要思路:
将手机页面上的验证码图片下载到电脑,使用OCR对图片进行识别,获取识别结果。并且使用jTessBoxEditor和Tesseract-OCR对验证码进行训练,提高识别成功率。
1:从手机下载验证码图片到电脑
手机端保存图片与浏览器端不同,不能通过url保存图片。需要进行对整个屏幕截图后,再通过图片对象的location属性进行局部截屏,从而保存图片,再使用图片的保存路径使用图片。
解决方法:当操作进入验证码所在页面时,对屏幕进行截图,获取验证码对象,获取其所在位置,在屏幕截图上按验证码所在位置截图验证码。具体代码如下:
from PIL import Image #需导入Image包
def get_screenshot_by_element(element):
location = element.location #获取验证码对象位置
size = element.size #获取验证码对象尺寸
box = (location["x"], location["y"], location["x"] + size["width"], location["y"] + size["height"]) #构建验证码对象坐标元组
screen_path = os.getcwd() + '\\screen_tmp.jpg'
captcha_path = os.getcwd() + '\\captcha_tmp.jpg'
global mobileDriver #这里使用了全局变量的webdriver
mobileDriver.get_screenshot_as_file(screen_path) #将页面截图并保存到指定路径
image = Image.open(screen_path) #打开该页面截图
newImage = image.crop(box) #对该页面截图验证码区域进行截图,传入图片的坐标元组
newImage.convert("RGB").save(captcha_path) #默认截图为png格式,即RGBA格式,需转换成RGB
说明:element是验证码对象,可通过captcha_image = mobileDriver.find_element_by_id(id)获得。
2、调用OCR对验证码进行识别
解决方式:直接使用命令行操作的方式调用tesseract OCR进行识别
主要代码:
def get_captcha_by_ocr():
cmd = 'tesseract ' + os.getcwd() + '\\captcha_tmp.jpg ' + os.getcwd() + '\\captcha_result'
print (cmd)
p = subprocess.Popen(cmd, shell=True)
p.wait() #等待进程执行完毕
f = open('./captcha_result.txt', 'r')
line = f.readline()
f.close()
return line.replace("\n", "")
说明:识别结果会保存在captcha_result中,通过文件读取验证码并且返回。
tesseract 安装和基本操作可查看:http://www.xue51.com/soft/1594.html#xzdz一文。
3、提高识别成功率的方式
直接使用默认识别方式成功率显然不高,可使用jTessBoxEditor对验证码进行训练。
(1)训练需要一定数量的验证码图片,可批量从APP页面中获取。
def get_captcha_pics():
global mobileDriver
captcha_image = mobileDriver.find_element_by_id('captcha-image')
location = captcha_image.location
size = captcha_image.size
box = (location["x"], location["y"], location["x"] + size["width"], location["y"] + size["height"])
#要截取几张,就range的N
for i in range(20):
print '获取第' + str(i) + '张'
#screen_path = os.getcwd() + '\\train_pic\\screen_tmp' + str(i) + '.png'
captcha_path = os.getcwd() + '\\train_pic\\captcha_tmp' + str(i) + '.png' #命令格式带序号后缀
global mobileDriver
mobileDriver.get_screenshot_as_file(captcha_path)
image = Image.open(captcha_path)
newImage = image.crop(box) #传入图片的坐标元组,进行截图
newImage.save(captcha_path) #默认截图为png格式,即RGBA格式,需转换成RGB
captcha_image.click() #点击切换图片
time.sleep(2)
实现思路:在验证码页面时,通过循环点击的方式切换验证码图片,并且保存每次的验证码,保存的思路和1中一样。
(2)使用jTessBoxEditor和tesseract进行训练,用训练模型进行识别提高正确率。
主要思路:类似以前大学做过的机器学习的思路,就是先采用jTessBoxEditor初步识别一定数量的验证码,并手动改正识别错误的数字,然后使用tesseract进行训练,生成训练模型。然后使用该训练模型进行识别,从而提高成功率。显然,后续训练的验证码图片越多,识别正确率越高。
训练的主要方法可看这篇文章:https://www.cnblogs.com/xpwi/p/9604567.html,注意要点如下:
1.jTessBoxEditor运行需要JDK1.8
2.加入训练的图片必须转换为tif\tiff格式,可通过python的image模块进行批量转换,直接保存为对应格式即可。
from PIL import Image
for i in range(100):
im = Image.open('./captcha_tmp' + str(i) + '.png')
#imL = im.convert('L') #转换为灰色
im.save('./tiff//captcha_tmp' + str(i) + '.tiff')
3.最后使用tesseract 图片名 结果文件名 -l num 的格式进行识别,-l num表示使用名称为num的训练集
从训练的效果来看:如果不使用训练集训练,识别20张丰收互联注册页面的验证码后,正确率不到20%,大部分还出现了数字以外的字符;而使用20张验证码进行训练后,正确率达到了50%,而且不会出现数字以外的字符。效果还是很明显的。