在web页面中,经常会遇到验证码,这对于我这么一个热爱web自动化测试人员,就变成了一件头疼的事。于是千方百计找各种资源得到破解简单的验证码方法。

识别验证码

  大致分如下几个步骤:

    1.获取验证码图片

    2.灰度处理

    3.增加对比度

    4.降噪

    5.识别

>>>>获取验证码

  通过各种方法,将含有验证码的图片获取并存贮在本地。

  本次的方法是:截取当前web页面,然后获取验证码在web页面中的位置,通过位置定位验证码图片再次截取。

  以163邮箱注册页面为例

  用到的库:selenium、PIL

  如果是python2.x,pip install PIL;在python3.x中PIL被移植到pillow 中,所以导入时需要导入pillow,pip install pillow  

 from PIL import Image

 import time
from selenium import webdriver def get_code_img(driver): time.sleep(1) # 截取整个浏览器图
driver.save_screenshot('webImg.png') # 获取code元素坐标
code_element = driver.find_element_by_id('vcodeImg') # 获取code图片坐标值
left_location = code_element.location['x']
top_location = code_element.location['y'] right_location = code_element.size['width'] + left_location
below_location = code_element.size['height'] + top_location # 通过坐标值得到code image图
web_img = Image.open("webImg.png")
code_img = web_img.crop((left_location,top_location,right_location,below_location))
code_img.save("codeImg.png")

  save_screenshot:webdriver中提供的一个方法,截取整个web页面

  code_element.location:获取某个的位置

  例如:print(code_element.location)的结果为:{'x': 632, 'y': 511}

  他是以图片的左上角为基准点,向右为x,向下为y

  code_element.size:获取图片的尺寸

  crop:是通过四个坐标点获取位置截图并且生成一张新图,他是Image 中的一个方法。

运行代码

 if __name__ == '__main__':

    base_url = 'http://reg.email.163.com/unireg/call.do?cmd=register.entrance&from=126mail'

    driver = webdriver.Chrome()
driver.maximize_window()
driver.get(base_url)
get_code_img(driver)
driver.close()

运行后获得两张图片webImg.png和codeImg.png。codeImg如下:

>>>>灰度处理/增加对比色

  将图片的颜色变成灰色并且增加对比色,识别时减少不必要的干扰。

 def gray_img(img):
code_img = Image.open(img)
# 转换为灰度
gray_img = code_img.convert('L')
# 增强亮度
enhance_img = ImageEnhance.Contrast(gray_img)
enhance_img = enhance_img.enhance(3)
return enhance_img if __name__ == '__main__': gray_img('codeImg.png').show()

  运行后结果

>>>>降噪

  根据一个点A的RGB值,与周围的4个点的RGB值进行比较,最初设定一个值N即判断数量(0<N<4),当A的RGB值与周围4个点的RGB相等数小于N时会被视为燥点,被消除。

 def clear_noise(img):

 noise_img = img.load()
# 获取图片的尺寸
w,h = img.size for y in range(1,h-1):
for x in range(1,w-1):
count = 0
if noise_img[x,y-1] > 245:
count = count + 1
if noise_img[x,y+1] > 245:
count = count + 1
if noise_img[x-1,y] > 245:
count = count + 1
if noise_img[x+1,y] > 245:
count = count + 1
if noise_img[x-1,y-1] > 245:
count = count + 1
if noise_img[x-1,y+1] > 245:
count = count + 1
if noise_img[x+1,y-1] > 245:
count = count + 1
if noise_img[x+1,y+1] > 245:
count = count + 1
if count > 4:
noise_img[x,y] = 255
return img if __name__ == '__main__':
img = gray_img('codeImg.png')
clear_noise(img).show()

运行后结果

>>>>识别

  识别使用的是pytesseract包。

  Pytesseract包依赖于tesseract,安装的时候两个都需安装

  详情参考

    tesseract: https://github.com/sirfz/tesserocr

    pytesseract:https://github.com/madmaze/pytesseract

 text = pytesseract.image_to_string(img)
print(text)

  很遗憾,上面的图没有识别出来。

完整代码运行识别

以下图验证码为例

 from PIL import Image, ImageEnhance
import time
import pytesseract
from selenium import webdriver def clear_noise(img):
noise_img = img.load()
# 获取图片的尺寸
w,h = img.size for y in range(1,h-1):
for x in range(1,w-1):
count = 0
if noise_img[x,y-1] > 245:
count = count + 1
if noise_img[x,y+1] > 245:
count = count + 1
if noise_img[x-1,y] > 245:
count = count + 1
if noise_img[x+1,y] > 245:
count = count + 1
if noise_img[x-1,y-1] > 245:
count = count + 1
if noise_img[x-1,y+1] > 245:
count = count + 1
if noise_img[x+1,y-1] > 245:
count = count + 1
if noise_img[x+1,y+1] > 245:
count = count + 1
if count > 4:
noise_img[x,y] = 255
return img def get_code_img(driver): time.sleep(1) # 截取整个浏览器图
driver.save_screenshot('webImg.png') # 获取code元素坐标
code_element = driver.find_element_by_id('vcodeImg') # 获取code图片坐标值
left_location = code_element.location['x']
top_location = code_element.location['y'] right_location = code_element.size['width'] + left_location
below_location = code_element.size['height'] + top_location # 通过坐标值得到code image图
web_img = Image.open("webImg.png")
code_img = web_img.crop((left_location,top_location,right_location,below_location))
code_img.save("codeImg.png") def gray_img(img):
code_img = Image.open(img)
# 转换为灰度
gray_img = code_img.convert('L')
# 增强亮度
enhance_img = ImageEnhance.Contrast(gray_img)
enhance_img = enhance_img.enhance(3)
return enhance_img if __name__ == '__main__': # base_url = 'http://reg.email.163.com/unireg/call.do?cmd=register.entrance&from=126mail'
#
# driver = webdriver.Chrome()
# driver.maximize_window()
# driver.get(base_url)
# get_code_img(driver)
# driver.close()
img = gray_img('d.png')
img = clear_noise(img)
img.show()
text = pytesseract.image_to_string(img)
print(text)

  运行结果

  虽然还是失败的。但至少已经接近了...

  此次只是对验证码的识别做简单的尝试。虽然此方法识别率不是很高。当然网上有很多收费的识别平台,通过大量联系识别率是很高的,有兴趣的可以去了解下。

  在认识验证码后我又来兴趣了,想去探个究竟验证码是怎样生成的...下次分享(皮一下)

python之验证码的生成

  在识别验证码的玩虐后,决定去看看他是怎么生成的。

 大致步骤:

1.创建图片

2.对背景像素处理

3.写入识别码

4.增加干扰线

5.滤镜处理

用到的库

 import random

 from PIL import Image, ImageFont, ImageDraw,ImageFilter

  在开始之前,了解下Image下图片的基本属性

  print(Image.open('img.jpeg'))

  结果:<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=500x291 at 0x103BA3FD0>

    打印的是:图片格式、mode:彩色值、size:尺寸

  也可以直接获取该图片的相关属性

  img = Image.open('img.jpeg')

  print(img.size, img.format, img.mode)

    结果: (500, 291) JPEG RGB

现在开始生成验证码

>>>>创建图片

 from PIL import Image

 width = 240
height = 60 # 图像生成
image = Image.new('RGB', (width,height), color='red')
image.show()

  new()是创建一个图片,第一个参数为图片mode也就是色彩值;

  第二个参数为图片的大小;

  第三个参数是图片颜色。

  show()方法是展示图片

  运行后结果

>>>>对背景像素处理

 # 填充每个像素点
for i in range(width):
for j in range(height ):
draw.point((i,j), fill=random_bgcolor())

  random_bgcolor():也是自定义的方法,随机产生颜色。

def random_bgcolor():
   return (random.randint(60,200), random.randint(60,200),random.randint(60,200))

  返回一个RGB色彩值,其中的颜色取值根据需要设置吧。

打印结果

>>>>写入识别码

 draw = ImageDraw.Draw(image)
# 写入信息
for i in range(4):
draw.text((60*i+10, 10), get_random(1,4), font=font, fill=random_color())

  ImageDraw.Draw(image)是在图片image上创建一个画笔

  For循环:循环产生4个数字或字母

  draw.text()方法是写入的内容,

    第一个参数是坐标,坐标自己通过图片尺寸稍为计算下,合理布局;

    第二个参数是写入的内容值,这里传入的是让系统随机产生一个数,方法可以自己定义;

    第三个font为字体,设置的字体必须存在

    第四个是对写入的内容附上颜色,这里传入的是让系统随机产生一个颜色,方法可以自己定义;

第二个参数的方法如下:

 def get_random(num,many):
for i in range(many):
s = ""
for j in range(num):
n = random.randint(1,2) # n==1生成数字,n=2生成字母
if n == 1:
num1 = random.randint(0, 9)
s +=str(num1)
else:
s +=str(random.choice(string.ascii_letters)) return s

第三个参数字体:

font = ImageFont.truetype('Arial.ttf',36)

第四个参数的方法如下:

  直接返回RGB颜色值

 def random_color():
return (random.randint(64,255), random.randint(64,255), random.randint(64,255))

  运行上面代码结果:

 

>>>>增加干扰线

  在生成的验证码图片上添加一条干扰线

 for i in range(2):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=random_bgcolor(),width=3)

  draw.line()是画线方法

  第一个参数:线条坐标,即位置。如上是在图片范围内位置随机

  第二个参数:线条的颜色,还是让随机产生

  第三个参数:线条的宽度,不设置的话默认为0

  运行结果

>>>>滤镜处理

  增加滤镜,可以增加颜色的不同

  很简单,一行代码搞定

 image = image.filter(ImageFilter.BLUR)

结果如下:

  非常抱歉,我设置产生的随机色颜色值没有调对,导致背景色和字体色颜色太接近,效果看起来不是很好。

  但是滤镜不是必须项,可以不设置。

完整代码如下

 import string

 import random
from PIL import Image, ImageFont, ImageDraw,ImageFilter # 生成随机大小数字
def get_random(num,many):
for i in range(many):
s = ""
for j in range(num):
n = random.randint(1,2) # n==1生成数字,n=2生成字母
if n == 1:
num1 = random.randint(0, 9)
s +=str(num1)
else:
s +=str(random.choice(string.ascii_letters))
return s # 随机颜色RGB
def random_color():
return (random.randint(64,255), random.randint(64,255), random.randint(64,255)) # 随机颜色RGB
def random_bgcolor():
return (random.randint(60,200), random.randint(60,200), random.randint(60,200)) # 字体,字体大小
font = ImageFont.truetype('Arial.ttf',36) # 图片尺寸
width = 240
height = 60 # 图像生成
image = Image.new('RGB', (width,height), color='red') # 创建绘图对象
draw = ImageDraw.Draw(image) # 填充背景色
for i in range(width):
for j in range(height):
draw.point((i,j), fill=random_bgcolor()) # 写入信息
for i in range(4):
draw.text((60*i+10, 10), get_random(1,4), font=font, fill=random_color()) # 插入干扰线
for i in range(2):
x1 = random.randint(0, width)
y1 = random.randint(0, height)
x2 = random.randint(0, width)
y2 = random.randint(0, height)
draw.line((x1, y1, x2, y2), fill=random_bgcolor(),width=3) # 添加滤镜
image = image.filter(ImageFilter.BLUR) # 展示图片
image.show() # 保存
image.save('code.png')

原文发布在 自动化软件测试 微信公众号,欢迎关注

原文地址:https://mp.weixin.qq.com/s/x3QT8njMX2wKPXKxqDPRyg

太嚣张了!他竟用Python绕过了“验证码”的更多相关文章

  1. pyinstaller打包的exe太大?你需要嵌入式python玄学 探索篇

    上篇我们讲到pip的安装以及普通库用pip的安装方法 CodingDog:pyinstaller打包的exe太大?你需要嵌入式python玄学 拓展篇​zhuanlan.zhihu.com 问题纷沓而 ...

  2. pyinstaller打包的exe太大?你需要嵌入式python玄学 拓展篇

    上篇我们讲到embedded版本的基础操作 CodingDog:pyinstaller打包的exe太大?你需要嵌入式python玄学 惊喜篇​zhuanlan.zhihu.com 可是却没有办法用pi ...

  3. pyinstaller打包的exe太大?你需要嵌入式python玄学 惊喜篇

    上篇讲到 pyinstaller打包exe太大的问题 CodingDog:pyinstaller打包的exe太大?你需要嵌入式python玄学 前提篇​zhuanlan.zhihu.com 那既然py ...

  4. Python随机生成验证码的两种方法

    Python随机生成验证码的方法有很多,今天给大家列举两种,大家也可以在这个基础上进行改造,设计出适合自己的验证码方法方法一:利用range Python随机生成验证码的方法有很多,今天给大家列举两种 ...

  5. Python识别网站验证码

    http://drops.wooyun.org/tips/6313 Python识别网站验证码 Manning · 2015/05/28 10:57 0x00 识别涉及技术 验证码识别涉及很多方面的内 ...

  6. python随机图片验证码的生成

    Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 1 2 3 4 5 6 7 8 9 from PIL import Im ...

  7. Python 生成随机验证码

    Python生成随机验证码  Python生成随机验证码,需要使用PIL模块. 安装: 1 pip3 install pillow 基本使用 1. 创建图片 1 2 3 4 5 6 7 8 9 fro ...

  8. Python生成随机验证码

    Python生成随机验证码,需要使用PIL模块. 安装: pip3 install pillow 基本使用 1.创建图片 from PIL import Image img = Image.new(m ...

  9. python 简单图像识别--验证码

    python  简单图像识别--验证码 记录下,准备工作安装过程很是麻烦. 首先库:pytesseract,image,tesseract,PIL windows安装PIL,直接exe进行安装更方便( ...

随机推荐

  1. ACM入门之OJ~

    所谓OJ,顾名思义Online Judge,一个用户提交的程序在Online Judge系统下执行时将受到比较严格的限制,包括运行时间限制,内存使用限制和安全限制等.用户程序执行的结果将被Online ...

  2. 用python复制图片、视频

    图片复制 f_src = open('1.jpg','rb') content = f_src.read() f_copy = open('1-副本.jpg','wb') f_copy.write(c ...

  3. 中国四大骨干网与十大ISP服务商

    1.骨干网 几台计算机连接起来,互相可以看到其他人的文件,这叫局域网,整个城市的计算机都连接起来,就是城域网,把城市之间连接起来的网就叫骨干网.这些骨干网是国家批准的可以直接和国外连接的互联网.其他有 ...

  4. ASP.NET Aries 高级开发教程:使用存储过程(番外篇)

    前言: 发现这个问题,有不少人提起过,所以就简单写成文章吧. 接下来看如何在Aries 框架中使用存储过程,整体步骤和绑定普通视图差不多. 步骤一:新建一个空视图. 可以在SqlCode管理中,创建一 ...

  5. Flarum轻量级论坛的安装

    论坛作为互联网中的远古产物,经历了如QQ群.社区和贴吧等新兴社交工具的冲击,依然能够存在,肯定是有着不可替代的用处,像吾爱.远景等论坛依旧火热.一些博客主也喜欢自己搭建一个论坛作为用户聚集之地. 之前 ...

  6. Oracle AWRSQRPT报告生成和性能分析

    我写的SQL调优专栏:https://blog.csdn.net/u014427391/article/category/8679315 对于局部的,比如某个页面列表sql,我们可以使用Oracle的 ...

  7. Mac电脑上一款非常时尚高清的动态壁纸Living Wallpaper HD

    很多朋友Mac电脑上都喜欢用动态壁纸,Living Wallpaper HD是本人尝试的一款非常不错的高清动态壁纸.有时钟.天气等各种组建,非常时尚美观. Living Wallpaper HD下载地 ...

  8. IDEA代码格式化快捷键(新)

    快捷键:Ctrl+Alt+L 效果: 之前: 之后:

  9. springboot~ObjectMapper~dto到entity的自动赋值

    实体与Dto自动赋值 在开发的过程中,实体之间相互赋值是很正常的事,但是我们一般的方法都通过set和get方法来进行的,如果要赋值的字段少那还行,但是需要赋值的字段超过10个,那就是个灾难,你会看到整 ...

  10. 避免Linux上错删文件

    前言 在linux上我们常见的问题就是一个操作不小心误删除文件,而且在linux想要恢复文件没这么简单.只有当每次删除之后才后悔莫及,参考windows中最常见的做法就是给系统装一个回收站,让每次删除 ...