Mac + Python + Selenium之获取验证码图片code并进行登录
Posted Owen_ET
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mac + Python + Selenium之获取验证码图片code并进行登录相关的知识,希望对你有一定的参考价值。
初稿代码,可以忽略不计(自己留着看)
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2020/01/15 13:27 # @Author : zc # @File : 115test.py from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep from PIL import Image,ImageEnhance import pytesseract imgPath1 = "/Users/zhangc/zh/111/test/img/识别失败图片.png" imgPath = "/Users/zhangc/zh/111/test/img/img.png" driver = webdriver.Chrome("/Users/zhangc/zh/111/test/chromedriver") def remove(string): return string.replace(" ","") def open(code): url = \'http://192.168.2.213:9100\' driver.get(url) driver.maximize_window() login(code) def login(code): if (code == "") | (len(remove(code)) != 4): getCodeImg() else: # 输入用户名 telephone = driver.find_element(By.NAME,"telephone") telephone.clear() telephone.send_keys("13642040631") # 输入密码 password = driver.find_element(By.NAME,"password") password.clear() password.send_keys("123456") # 输入验证码 code_loc = driver.find_element(By.NAME,"code") code_loc.clear() code_loc.send_keys(code) # 点击登录按钮 button = driver.find_element(By.XPATH,"//button[@type=\'button\']") button.click() try: # 后台获取验证码校验内容 text1 = driver.find_element(By.CSS_SELECTOR, ".el-message__content").text print(text1) while text1 == "": button.click() text1 # 前台获取验证码校验内容 text2 = driver.find_element(By.CSS_SELECTOR, ".el-el-form-item__error").text print(text2) if text1 == "验证码不正确": print("验证码不正确") driver.find_element(By.XPATH, "//div[@class=\'divIdentifyingCode\']/img").click() getCodeImg() code2 = test() login(code2) elif text2 == "请输入正确的验证码": print("请输入正确的验证码") driver.find_element(By.XPATH, "//div[@class=\'divIdentifyingCode\']/img").click() getCodeImg() code2 = test() login(code2) else: print("登陆成功!") except: print("进入首页!!!!") pass def getCodeImg(): \'\'\'获取code图片\'\'\' size2 = driver.get_window_size() print("页面的总size:"+str(size2)) img_el = driver.find_element(By.XPATH,"//div[@class=\'divIdentifyingCode\']/img") # 获取图片的坐标 location = img_el.location print("页面坐标点的size:"+str(location)) # 获取图片的大小 size = img_el.size print("验证码的size:"+str(size)) left = location[\'x\']/size2[\'width\'] top = location[\'y\']/size2[\'height\'] right = (location[\'x\'] + size[\'width\'])/size2[\'width\'] bottom = (location[\'y\'] + size[\'height\'])/size2[\'height\'] print(left,top,right,bottom) # 截图操作 driver.get_screenshot_as_file(imgPath) imgSize = Image.open(imgPath).size print("截图的size:"+str(imgSize)) sleep(2) img = Image.open(imgPath).crop((left*imgSize[0], top*imgSize[1]+100, right*imgSize[0]+20, bottom*imgSize[1]+150)) img = img.convert(\'L\') #转换模式:L | RGB img = ImageEnhance.Contrast(img)#增强对比度 img = img.enhance(2.0) #增加饱和度 img.save(imgPath) def test(): img2 = Image.open(imgPath) code = pytesseract.image_to_string(img2).strip() print("=============输出的验证码为:"+remove(code)) while (code == "") | (len(remove(code)) != 4): # 重新获取验证码 driver.find_element(By.XPATH, "//div[@class=\'divIdentifyingCode\']/img").click() getCodeImg() img2 = Image.open(imgPath) code = pytesseract.image_to_string(img2).strip() if code == "": print("code获取为空值=================") continue elif len(remove(code)) != 4: print("code获取不是4位数字=============") continue else: print("识别成功!") # break break print("=============输出的验证码为:" + remove(code)) return remove(code) if __name__ == \'__main__\': code = "" open(code) code1 = test() login(code1) # 页面的总size:{\'width\': 1206, \'height\': 1129} # 页面坐标点的size:{\'x\': 961, \'y\': 518} # 验证码的size:{\'height\': 28, \'width\': 70} # 0.796849087893864 0.4588131089459699 0.8548922056384743 0.48361381753764393 # 截图的size:(2412, 1950)
====================下面看正文=========================
之前有个问题一直在困扰着我,如何获取验证码的值
后来查询大神们的文章得知:
用pytesseract库来读取图片的文字。
先安装两个库:
# python有着更加优雅的方式调用系统的tesseract工具,首先安装pytesseract模块;pytesseract是对tesseract的封装,要和PIL联合使用 # 安装pytesseract sudo pip install pytesseract # 安装图片处理器PIL pip install pillow
好了接下来看看我是怎么一步一步实现的吧
第一步、保存验证码图片
核心代码:
getCodeImg()方法
import pytesseract from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep from PIL import Image,ImageEnhance class LoginCode(object): # 用户名框元素 telephone_loc = (By.NAME,"telephone") # 密码框元素 password_loc = (By.NAME,"password") # 验证码框元素 code_loc = (By.NAME,"code") # 登录按钮元素 button_loc = (By.XPATH,"//button[@type=\'button\']") # 验证码图片元素 img_el_loc = (By.XPATH, "//div[@class=\'divIdentifyingCode\']/img") # 验证码错误提示元素 codeErrMsg_loc = (By.CSS_SELECTOR, ".el-message__content") imgPath = "/Users/zhangc/zh/111/test/img/img.png" driver = webdriver.Chrome("/Users/zhangc/zh/111/test/chromedriver") def find_element(self,*loc): # 实验得知方法中的参数loc↑加上*,定位会更稳定 \'\'\'定位单个元素\'\'\' return self.driver.find_element(*loc)
# 核心代码↓ def getCodeImg(self): \'\'\'获取验证码图片\'\'\' # 验证码图片的元素定位 img_el = self.find_element(*self.img_el_loc) # 获取整个浏览器的size chromeSize = self.driver.get_window_size() print("页面的总size:"+str(chromeSize))
# 页面的总size:{\'width\': 1202, \'height\': 1129} # 获取图片的坐标 self.location = img_el.location print("页面坐标点的size:"+str(self.location))
# 页面坐标点的size:{\'x\': 959, \'y\': 518} x:指的图片左边距;y:指的图片上边距
# 获取图片的大小 imgSize = img_el.size print("验证码的size:"+str(imgSize))
# 验证码的size:{\'height\': 28, \'width\': 70}
# 左边距占整个浏览器的百分比
left = self.location[\'x\']/chromeSize[\'width\']
# 上边距占整个浏览器的百分比 top = self.location[\'y\']/chromeSize[\'height\']
# 右边距占整个浏览器的百分比 right = (self.location[\'x\'] + imgSize[\'width\'])/chromeSize[\'width\']
# 下边距占整个浏览器的百分比 bottom = (self.location[\'y\'] + imgSize[\'height\'])/chromeSize[\'height\']
print(left,top,right,bottom)
# 0.7978369384359401 0.4588131089459699 0.8560732113144759 0.48361381753764393 # 浏览器截屏操作 self.driver.get_screenshot_as_file(self.imgPath) screenshotImgSize = Image.open(self.imgPath).size print("截图的size:"+str(screenshotImgSize))
# 截图的size:(2404, 1950) 宽:2404,高:1950 sleep(2) # 从文件读取截图,截取验证码位置再次保存 img = Image.open(self.imgPath).crop(( # left*screenshotImgSize[0], # top*screenshotImgSize[1]+100, # right*screenshotImgSize[0]+20, # bottom*screenshotImgSize[1]+150
# 左边距百分比*截图的高≈截图左边距,再加上微调的距离+350
left * screenshotImgSize[1]+350,
# 上边距百分比*截图的高≈截图左边距,再加上微调的距离-100 top * screenshotImgSize[0]-100,
# 右边距百分比*截图的宽≈截图上边距,再加上微调的距离+400 right * screenshotImgSize[1]+400,
# 下边距百分比*截图的高≈截图右边距,再加上微调的距离-50 bottom * screenshotImgSize[0]-50 )) img = img.convert(\'L\') # 转换模式:L | RGB img = ImageEnhance.Contrast(img) # 增强对比度 img = img.enhance(2.0) # 增加饱和度 img.save(self.imgPath) # 再次保存图片
获取页面中验证码图片的截图:
第二步、循环获取验证码截图的code
为什么要循环获取呢,一次获取不就可以了吗,原因是图片识别文字不准确,经常会识别为空或者不是4位数的值。
所以要循环做判断,下面上代码:
核心方法是:
①getCode():先获取图片code值
②loopGetCode():如果获取的code值不符合条件,循环判断获取正确的图片code值
import pytesseract from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep from PIL import Image,ImageEnhance class LoginCode(object): # 用户名框元素 telephone_loc = (By.NAME,"telephone") # 密码框元素 password_loc = (By.NAME,"password") # 验证码框元素 code_loc = (By.NAME,"code") # 登录按钮元素 button_loc = (By.XPATH,"//button[@type=\'button\']") # 验证码图片元素 img_el_loc = (By.XPATH, "//div[@class=\'divIdentifyingCode\']/img") # 验证码错误提示元素 codeErrMsg_loc = (By.CSS_SELECTOR, ".el-message__content") imgPath = "/Users/zhangc/zh/111/test/img/img.png" driver = webdriver.Chrome("/Users/zhangc/zh/111/test/chromedriver") def remove(self,string): \'\'\'字符串去除空格\'\'\' return string.replace(" ","") def find_element(self,*loc): # 实验得知方法中的参数loc↑加上*,定位会更稳定 \'\'\'定位单个元素\'\'\' return self.driver.find_element(*loc)
# 核心代码↓ def getCode(self): \'\'\'获取图片的code\'\'\' # 再次读取识别验证码 img = Image.open(self.imgPath) code = pytesseract.image_to_string(img).strip() print("=============输出的验证码为:" + self.remove(code)) return code
# 核心代码↓ def loopGetCode(self): \'\'\'循环判断获取正确的图片code\'\'\' code = self.remove(self.getCode()) # 循环前获取code字数 codeNumBf = len(code) # 如果获取图片的code值为空或者不满足4位数进行循环 while (code == "") | (codeNumBf != 4): # 重新获取验证码 self.find_element(*self.img_el_loc).click() self.getCodeImg() # 获取验证码图片 code = self.remove(self.getCode()) # 循环后获取code字数 codeNumAf = len(code) if code == "": print("code获取为空值=================") continue elif codeNumAf != 4: print("code获取不是4位数字=============") continue else: print("识别成功!") # 识别成功退出循环 break print("=============输出的验证码为:" + code) # 输出满足条件的code return code
三、进行登录操作并判断验证码正确性
为什么登陆操作时还要判断验证码正确性呢,因为还是图片识别文字不准确,虽然识别出4位数但是并不是验证码图片中的值,所以需要再次判断,如果验证码错误就重新获取验证码的值。
核心代码:
login():登录操作
import pytesseract from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep from PIL import Image,ImageEnhance class LoginCode(object): # 用户名框元素 telephone_loc = (By.NAME,"telephone") # 密码框元素 password_loc = (By.NAME,"password") # 验证码框元素 code_loc = (By.NAME,"code") # 登录按钮元素 button_loc = (By.XPATH,"//button[@type=\'button\']") # 验证码图片元素 img_el_loc = (By.XPATH, "//div[@class=\'divIdentifyingCode\']/img") # 验证码错误提示元素 codeErrMsg_loc = (By.CSS_SELECTOR, ".el-message__content") imgPath = "/Users/zhangc/zh/111/test/img/img.png" driver = webdriver.Chrome("/Users/zhangc/zh/111/test/chromedriver") def open(self): \'\'\'打开浏览器\'\'\' url = \'http://192.168.2.213:9100\' self.driver.get(url) self.driver.maximize_window() self.driver.implicitly_wait(10) # 获取验证码图片 self.getCodeImg() # 核心代码↓ def login(self,code): \'\'\'进行登录操作\'\'\' # 输入用户名 telephone = self.find_element(*self.telephone_loc) telephone.clear() telephone.send_keys("13642040631") # 输入密码 password = self.find_element(*self.password_loc) password.clear() password.send_keys("123456") # 输入验证码 code_loc = self.find_element(*self.code_loc) code_loc.clear() code_loc.send_keys(code) # 点击登录按钮 button = self.find_element(*self.button_loc) button.click() sleep(0.5) try: # 后台获取验证码校验内容 codeErrMsg = self.find_element(*self.codeErrMsg_loc).text print("打印后台:"+codeErrMsg) if codeErrMsg == "验证码不正确": print("验证码不正确111") self.find_element(*self.img_el_loc).click() self.getCodeImg() self.loopGetCode_action() else: print("登陆成功!") except: print("进入首页!!!!") pass # 核心相关代码↓ def loopGetCode_action(self): \'\'\'循环验证code的正确性\'\'\' resultCode = self.loopGetCode() self.login(resultCode) # 核心相关代码↓ def login_action(self): \'\'\'执行验证码登录操作\'\'\' # 打开浏览器并获取验证码图片 self.open() self.loopGetCode_action()
以上三步就是完整获取图片文字的方法了,虽然有点多但是都是必不可少的步骤。
==========================================================
注:需要安装tesseract,不然会提示:
# CHANGE THIS IF TESSERACT IS NOT IN YOUR PATH, OR IS NAMED DIFFERENTLY
pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it\'s not in your path
未找到tesseract的路径,需要进入pytesseract.py文件
# Mac安装tesseract brew install --with-training-tools tesseract # 查看版本 tesseract -v tesseract 4.0.0 leptonica-1.77.0 libgif 5.1.4 : libjpeg 9c : libpng 1.6.36 : libtiff 4.0.10 : zlib 1.2.11 : libwebp 1.0.2 : libopenjp2 2.3.0 Found AVX2 Found AVX Found SSE # 查看安装路径 which tesseract /usr/local/bin/tesseract
==========================================================
下面上完整代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2020/01/15 13:27 # @Author : zc # @File : 115test.py import pytesseract from selenium import webdriver from selenium.webdriver.common.by import By from time import sleep from PIL import Image,ImageEnhance class LoginCode(object): # 用户名框元素 telephone_loc = (By.NAME,"telephone") # 密码框元素 password_loc = (By.NAME,"password") # 验证码框元素 code_loc = (By.NAME,"code") # 登录按钮元素 button_loc = (By.XPATH,"//button[@type=\'button\']") # 验证码图片元素 img_el_loc = (By.XPATH, "//div[@class=\'divIdentifyingCode\']/img") # 验证码错误提示元素 codeErrMsg_loc = (By.CSS_SELECTOR, ".el-message__content") imgPath = "/Users/zhangc/zh/111/test/img/img.png" driver = webdriver.Chrome("/Users/zhangc/zh/111/test/chromedriver") def remove(self,string): \'\'\'字符串去除空格\'\'\' return string.replace(" ","") def find_element(self,*loc): # 实验得知方法中的参数loc↑加上*,定位会更稳定 \'\'\'定位单个元素\'\'\' return self.driver.find_element(*loc) def open(self): \'\'\'打开浏览器\'\'\' url = \'http://192.168.2.213:9100\' self.driver.get(url) self.driver.maximize_window() self.driver.implicitly_wait(10) # 获取验证码图片 self.getCodeImg() def getCodeImg(self): \'\'\'获取验证码图片\'\'\' # 验证码图片的元素定位 img_el = self.find_element(*self.img_el_loc) # 获取整个浏览器的size chromeSize = self.driver.get_window_size() print("页面的总size:"+str(chromeSize)) # 页面的总size:{\'width\': 1202, \'height\': 1129} # 获取图片的坐标 self.location = img_el.location print("页面坐标点的size:"+str(self.location以上是关于Mac + Python + Selenium之获取验证码图片code并进行登录的主要内容,如果未能解决你的问题,请参考以下文章