解决验证码的方法:
方法一:让开发帮忙去掉验证码代码,重新部署环境。(不推荐)
方法二:弄个万能验证码,每次登陆都可以登陆。(不推荐)
方法三:用cookie添加登陆名和密码避开验证码的方式。(我还不会)
方法四:老老实实获取验证码。(重点讲这个)
采用方法四需要引用第三方库:pytesseract,该库依赖于Tesseract,所以需要先安装Tesseract。
1、
git文档地址:https://digi.bib.uni-mannheim.de/tesseract/
请安装不带dev的稳定版,下载后就是一个exe安装包,直接右击安装即可。
2、
3、配置环境变量:
(1)编辑系统变量里面 path,添加下面的安装路径:C:\Program Files (x86)\Tesseract-OCR
(2)添加TESSDATA_PREFIX变量,值为:C:\Program Files (x86)\Tesseract-OCR\tessdata
cmd命令模式下测试是否安装成功:
tesseract test.jpg text -l chi_sim
4、安装python的第三方库:
pip install pillow #一个python的图像处理库,pytesseract依赖
pip install pytesseract
5、找到pytesseract的安装包,C:\Python34\Lib\site-packages\pytesseract,编辑pytesseract.py文件(此步骤必须做,否则运行代码时会报错):
tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'
获取验证码有2种思路:
1、截图登陆页面,再截取验证码图片,识别;
2、直接在登陆页面,定位到验证码,将验证码图片另存为,识别;
思路一具体实现过程:
(1)先计算浏览器与登陆页面截图的比例值,再计算对应的验证码图片位置。不这样做的话,会导致获取的验证码位置不正确。
browser.maximize_window() #获取浏览器大小 size_window = browser.get_window_size() time.sleep(1) #获取截图 browser.save_screenshot('login.png') login_img = Image.open('login.png') (login_width,login_height) = login_img.size logger.info('截图的宽高:') logger.info(login_width,login_height) #计算浏览器与截图比例 scale = size_window['width'] / login_width #获取验证码 code_loc = browser.find_element_by_xpath('//*[@id="valiCode"]').location code_size = browser.find_element_by_xpath('//*[@id="valiCode"]').size #获取验证码位置 #此处的X和Y分别加了数字,因为前端的样式中,验证码标签img的margin-left为15,margin-top为5 location_X = math.ceil(code_loc['x'] / scale) + 15 location_Y = math.ceil(code_loc['y'] / scale) + 5 location_height = math.ceil(code_size['height'] / scale) location_width = math.ceil(code_size['width'] / scale) code_img = login_img.crop((location_X,location_Y,location_X + location_width ,location_Y + location_height)) code_img.save('code.png')
(2)再将获取到的验证码图片,先进行二值化处理,以便提取验证码更容易,这里涉及一些图像处理的算法。
#先二值化处理 image=Image.open(img) # 灰度图 lim=image.convert('L') # 灰度阈值设为100,低于这个值的点全部填白色 threshold=100 table=[] for j in range(256): if j<threshold: table.append(0) else: table.append(1) bim=lim.point(table,'1') bim.save('newImg.png')
(3)处理后的图像更容易获取验证码,这里采用pytesseract库转化,注意后面的参数设置。
先前不设置参数时,总是将1转化为7,设置后转化的准确率杠杠滴。
当然,目前只是识别数字型的验证码,文字类型的方法应该是类似的。
lastpic = Image.open('newImg.png') text = pytesseract.image_to_string(lastpic,lang='eng',config='--psm 6 --oem 3 -c tessedit_char_whitelist=0123456789').strip() #后面的配置简直是神器啊,之前一直将1读成7,加配置后很准确 with open('output.txt','w') as f: f.write(text) with open('output.txt','r') as f: code = f.read() f.close() logger.info("获取的验证码为:") logger.info(code)
思路二具体实现过程:
(1)先定位到登陆页面中验证码的位置,将验证码图片另存到一个路径下,并且返回最新时间保存的图片。
# 把验证码另存为图片 def image_save_as(): image = driver.find_element_by_id("valiCode") actions = ActionChains(driver) actions.context_click(image) actions.perform() pyautogui.typewrite(['down', 'down', 'enter', 'enter']) # 右键找到图片另存为 sleep(2) pyautogui.typewrite(['enter']) sleep(2) def get_newest_image(image_path): lists = os.listdir(image_path) lists.sort(key=lambda fn:os.path.getmtime(image_path + "\\" + fn)) # 按时间排序 image_new = os.path.join(image_path, lists[-1]) return image_new
(2)后面的处理过程与思路一的图片处理方法相同。