一、环境准备:
任务 | python验证码识别 |
---|---|
语言 | python 版本3.7 |
语言工具 | pycharm 版本2018.2.2 |
工具 | selenium 版本3.14 |
技术1 | 接口识别库 request |
技术2 | 图片切割库 pillow |
二、方法
1、万能能验证码—(缺点:不算模拟用户行为)
2、注释验证码相关的后台代码(缺点:繁琐,需要修改代码)
3、OCR技术(python库缺点,识别率低于20%)
4、保存服务端的cookie值(保留成功状态。缺点:并未做登录操作,跳过这个问题,而不是解决这个问题)
5、电脑使用内网ip地址,根据绑定的ip,不需要输入验证码
6、通过第三方工具,根据图片识别文字的工具。缺点:准确率低
7、通过第三方网站,易源网站,识别验证码。优点:准确率高,收费
8、输入验证码前,加入时间等待15秒。手动输入验证码。这个方式很笨
三、方法详解:万能验证码的设置:
1、如何查看系统是否存在万能验证码
(1)确认源代码位置
(2)了解MVC设计模式
1 | 2 |
---|---|
model 模型层 | 数据库相关。新增用户信息时,通过user类创建一个user对象,就会向数据库保存用户信息。(user类里有和表对应的属性,user表存储用户信息) |
view界面层 | 前端界面相关。用于收集和显示,用户的输入数据和服务器端的输出数据 |
control 控制层 | 处理业务逻辑 ,负责系统所有的业务逻辑处理 |
判断验证码是否登录成功,属于业务逻辑,代码在control层。找验证码代码,需要先找登录功能代码。分析登录页面网址
#登录页面地址
http://127.0.0.1/index.php?m=admin&c=public&a=login
#分析这三个参数
m=admin&c=public&a=login
m是模块,一个模块就是一个文件夹,一个文件夹对应某一个包名
c是controller,一个控制器,一般是一个类,也就是一个类文件
a是action,是一个行为动作,一个动作就是代码里的某个方法
根据这三个参数,找到对应的文件,在代码里找到验证码相关的代码
分析:假如代码中,含有:
#验证码不正确的时候,if条件的判断代码,代码里有
if((..........)!='1234')
验证码不正确
#所以,万能验证码为1234
2、添加万能验证码
四、方法详解:第三方网站,识别验证码
1、要求:
UI自动化,需要测试时,尽量仿真的模拟用户行为
2、知识拓展:
易源网站(万维易源)封装了很多人工智能算法,登录网站搜索“验证码识别”,查询到相关接口。(收费)
网站:https://www.showapi.com/
3、使用此处的验证码接口需要什么东西?
(1)接口的使用环境,本质:调用了python的request库。所以使用时,需要request库。
如图,右侧【SDK下载】下载SDK是个压缩文件,解压后是一个py文件,放到工程目录下
(2)接口地址(识别英文_文件):http://route.showapi.com/184-4
接口收费,访问地址需要如下(购买后得到)
(a)App_ID:用户id、
(b)App_sceret:密码
(3)接口参数:
image:图片的地址
typeId:告诉接口,识别验证码的类型,(使用方法见网站内解释)
convert_to_jpg:不需要图片转换
3、解决方案:通过接口识别方法
优点:能识别具体内容,识别率为90%
缺点:只能是中文验证码和数字验证码、英文验证码(12306的无法识别)
四、实现
步骤:
(1)通过selenium启动浏览器,识别用户名和密码
(2)将浏览器中的登录信息进行截图,切割验证码(使用pillow库)
(3)针对浏览器中的验证码图片进行识别(易源网站的验证码识别接口)
五、原代码
#1.准备 使用Selenium启动浏览器识别用户名和密码
from PIL import Image
from selenium import webdriver
from ShowapiRequest import ShowapiRequest
jwdriver=webdriver.Chrome() #调用chrome浏览器
# 打开浏览器
jwdriver.get("http://127.0.0.1/iwebshop/index.php?controller=systemadmin")
#定位用户名输入框 并且输入内容
jwdriver.find_element_by_name("admin_name").send_keys("admin")
#定位密码输入框 并且输入内容
jwdriver.find_element_by_name("password").send_keys("123456")
#2.截图浏览器中的图片 进行切割(Pillow库)
# 从网页中提取出验证码图片
def jietu():
jwdriver.save_screenshot("C:/jw123all.png")
# 使用坐标方式
# 拿到验证码左上角坐标
left_top=jwdriver.find_element_by_id("captchaImg").location
print("左上角坐标",left_top)
#左上角的x轴坐标
#左上角的y轴坐标
left=left_top['x']
top= left_top['y']
# 取出右下角坐标
# 获取图片的宽度+left x1 =====》 右坐标
#获取图片的高度+top y1 =====》 下坐标
#定位图片
img=jwdriver.find_element_by_id("captchaImg")
right=img.size['width']+left
down=img.size['height']+top
print("四个点的坐标",left,top,right,down)
# 利用这四个坐标切割图片
# 1.打开图片
jw_img=Image.open("C:/jw123all.png")
jw_img22=jw_img.crop((left,top,right,down))
# 保存到硬盘上
jw_img22.save("C:/jwyanzhengma.png")
#3.再针对验证码进行识别(易源的接口)
def shibieyanzhengma():
# 使用接口环境访问接口地址===>前提要注意联网
jw1=ShowapiRequest("http://route.showapi.com/184-4","75989","10186a47079e4b8085ddb9bf168d3f70")
# 增加接口请求的参数
jw1.addBodyPara("typeId","25")
jw1.addBodyPara("convert_to_jpg","0")
# 告诉接口识别的验证码图片文件
jw1.addFilePara("image","c:/jwyanzhengma.png")
#访问接口
result=jw1.post().json()
#从json提炼出有效的数据
text=result['showapi_res_body']['Result']
print("验证码是",text)
return text
if __name__=="__main__":
jietu()
# 调用验证码函数获取结果
yanzhengma=shibieyanzhengma()
#将验证码放到网页上
jwdriver.find_element_by_name("captcha").send_keys(yanzhengma)
六、我的练习代码
#导入webdriver类包
from PIL import Image
from selenium import webdriver
from ShowapiRequest import ShowapiRequest
#调用谷歌浏览器
webdriver = webdriver.Chrome()
#打开谷歌浏览器
webdriver.get('网址')
#定位元素,用户名,输入内容
webdriver.find_element_by_id('用户名的id').send_keys('user')
#定位元素,密码,输入内容
webdriver.find_element_by_id('密码的id').send_keys('111111')
#定义函数,截取验证码图片
def picture_screenshoot():
#从网页中提取验证码图片
webdriver.save_screenshot('D:\图片文件名.png')
#获取验证码左上角坐标,格式:{'x':100,'y':200}
left_top = webdriver.find_element_by_id('验证码的id').location
print('左上角坐标',left_top)
#X轴坐标
x = left_top['x']
#Y轴坐标
y = left_top['y']
#获取右下角的图标,先获取验证码的长和宽
#宽度+x = x1
ver_img = webdriver.find_element_by_id('验证码的id')
x1 = ver_img.size['width']+x
#高度+y = y1
y1 = ver_img.size['hight']+y
#使用四个坐标,切割验证码(使用pillow库),
#需要安装pillow库,否则没有Imag对象
#打开图片,在硬盘中的图片加载到内存中
ver_img2 = Image.open('D:\图片文件名.png')
#传入四个坐标值
ver_img2.crop(x,y,x1,y1)
#将截取的验证码保存到硬盘上
ver_img2.save('D:\验证码图片名.png')
#定义函数,识别验证码
def verif_pic_identified():
#使用接口环境,访问接口地址,必须联网访问
req = ShowapiRequest('http://route.showapi.com/184-4')
#增加接口请求参数
req.addBodyPara('typeId','25')
req.addBodyPara('convert_to_jpg', '0' )
#告诉接口识别的验证码图片文件
req.addFilePara('imag','D:\验证码图片名.png')
#访问接口
response = req.post().json()
print(response)
#从json中,提取有效验证码数据
text = response['shouapi_res_body']['Result']
print(text)
return text
if __name__ == '__main__':
picture_screenshoot()
yanzhengma = verif_pic_identified()
webdriver.find_element_by_id('验证码id').send_keys(yanzhengma)
七、无注释代码
from PIL import Image
from selenium import webdriver
from ShowapiRequest import ShowapiRequest
jwdriver=webdriver.Chrome()
jwdriver.get("http://127.0.0.1/iwebshop/index.php?controller=systemadmin")
jwdriver.find_element_by_name("admin_name").send_keys("admin")
jwdriver.find_element_by_name("password").send_keys("123456")
def jietu():
jwdriver.save_screenshot("C:/jw123all.png")
left_top=jwdriver.find_element_by_id("captchaImg").location
print("左上角坐标",left_top)
left=left_top['x']
top= left_top['y']
img=jwdriver.find_element_by_id("captchaImg")
right=img.size['width']+left
down=img.size['height']+top
print("四个点的坐标",left,top,right,down)
jw_img=Image.open("C:/jw123all.png")
jw_img22=jw_img.crop((left,top,right,down))
jw_img22.save("C:/jwyanzhengma.png")
#3.再针对验证码进行识别(易源的接口)
def shibieyanzhengma():
jw1=ShowapiRequest("http://route.showapi.com/184-4","75989","10186a47079e4b8085ddb9bf168d3f70")
jw1.addBodyPara("typeId","25")
jw1.addBodyPara("convert_to_jpg","0")
jw1.addFilePara("image","c:/jwyanzhengma.png")
result=jw1.post().json()
text=result['showapi_res_body']['Result']
print("验证码是",text)
return text
if __name__=="__main__":
jietu()
yanzhengma=shibieyanzhengma()
jwdriver.find_element_by_name("captcha").send_keys(yanzhengma)