前言:本篇主要记录在项目登录过程中验证码的问题,基于pytesseract和PIL组件实现简单的验证码图片识别;需要自行配置pytesseract,PIL环境。
目标:获取验证码、自动输入实现登录
一、截取验证码图片信息并保存
访问目标界面,截取全屏后,对验证码图片元素定位,获取元素的坐标数据,比如元素高、宽。精确截图获取验证码图片信息。
—代码展示
# 1访问界面
url = '#手动打码#'
driver = webdriver.Chrome()
driver.get(url)
# 2调整页面屏幕分辨率
driver.execute_script('document.body.style.zoom="0.8"')
time.sleep(2)
# 验证码截取、保存
img = driver.find_element(By.ID, 'randImage') # 要截图的元素
x, y = img.location.values() # 元素 坐标数据
h, w = img.size.values() # 元素高宽
# 将截图以二进制的形式返回
img_data = driver.get_screenshot_as_png()
# 以新图片的形式打开返回的数据
sreenshots = Image.open(BytesIO(img_data))
# 对截图进行剪切
result = sreenshots.crop((x, y, x + w, y + h)) # 元素大小放缩
# 存储
imgpath = 'D:\\picture\\' + "001.png"
result.save(imgpath)
—效果展示
二、识别验证码图片,获取代码
读取存储的图片信息,获取验证码。对图片进行两步处理:转化成灰度,二值化处理;经过处理的图片便于识别。
—代码展示
im= Image.open("D:\\picture\\001.png")
#1.转化成灰度
imgry = im.convert('L')
#imgry.show()
threshold = 101 # 140 这里需要自行调整,如果不能打印验证码自行调整
table = []
#2.二值化处理
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = imgry.point(table, '1')
out.show()
#3.识别验证码
code = pytesseract.image_to_string(out)
print("验证码拿来吧->", code)
—效果展示
三、完整的示例
本示例将图片截取,验证码的识别分别进行了封装实现,使代码更加一目了然,功能点分明,助于后续的展开式使用。
—代码展示
from selenium import webdriver
from selenium.webdriver.common.by import By
from PIL import Image
from io import BytesIO
import pytesseract
import time
## 截取验证码,保存
def img_save(img,driver):
x, y = img.location.values() # 元素 坐标数据
h, w = img.size.values() # 元素高宽
# 将截图以二进制的形式返回
img_data = driver.get_screenshot_as_png()
# 以新图片的形式打开返回的数据
sreenshots = Image.open(BytesIO(img_data))
# 对截图进行剪切
result = sreenshots.crop((x, y, x + w, y + h)) # 元素大小放缩
# 存储
imgpath = 'D:\\picture\\' + "003.png"
result.save(imgpath)
return imgpath
##识别验证码图片,获取代码
def get_imgCode(imgpath):
im = Image.open(imgpath)
#1.转化成灰度
imgry = im.convert('L')
threshold = 101.5 # 140
table = []
#2.二值化处理
for i in range(256):
if i < threshold:
table.append(0)
else:
table.append(1)
out = imgry.point(table, '1')
out.show()
#3.识别验证码
code = pytesseract.image_to_string(out)
return code
if __name__ == '__main__':
# 1访问界面
url = '#手动打码#'
driver = webdriver.Chrome()
driver.get(url)
# 2调整页面屏幕分辨率
driver.execute_script('document.body.style.zoom="0.8"')
time.sleep(2)
# 验证码截取、保存
img = driver.find_element(By.ID, 'randImage') # 要截图的元素
imgpath = img_save(img,driver)
code = get_imgCode(imgpath)
print("验证码拿来吧->", code)
# 退出浏览器
driver.quit()
小彩蛋
问题:无法正确截取验证码的位置
原因:本身笔记本放缩到125%,浏览器需要回滚到100%的缩放
解决:添加屏幕调节函数execute_script(N),其中系数N的计算方式是 原放缩比例*N=100%,比如当前的放缩为200%,则N为0.5
代码:
#1访问界面
url = '#手动打码#'
driver = webdriver.Chrome()
driver.get(url)
#2调整页面屏幕分辨率
driver.execute_script('document.body.style.zoom="0.8"')
time.sleep(2)
#验证码截取、保存
img = driver.find_element(By.ID, 'randImage') # 要截图的元素
x, y = img.location.values() # 元素 坐标数据
h, w = img.size.values() # 元素高宽
# 将截图以二进制的形式返回
img_data = driver.get_screenshot_as_png()
# 以新图片的形式打开返回的数据
sreenshots = Image.open(BytesIO(img_data))
# 对截图进行剪切
result = sreenshots.crop((x, y, x + w, y + h)) # 元素大小放缩
# 存储
imgpath = 'D:' + '\\picture\\' + "003.png"
result.save(imgpath)