1、任务任务6 6 反爬虫技术反爬虫技术主流验证码解析主流验证码解析本章学习目标 了解图形验证码的基本含义 掌握tesserocr库的安装和基本用法 了解使用tesserocr解析自定义图形验证码 了解滑动验证码的基本概念 了解Selenium和ChromeDriver的安装和配置并实现滑动验证码的解析 了解点击式验证码的基本概念并其技术特点 了解聚合数据平台接口的网络API的使用方式并实现点击式证码的解析6.1.5 自定义图形验证码的生成【实例6-1】本实例使用一个较为简单的图形验证码作为案例来讲解一下图形验证码解析的过程。首先,使用Python通过导入特定模块生成一个比较简单的图形验证码。具体
2、步骤介绍如下:1)导入random模块,该模块用于生成图形验证码的随机数字。例如,random.randint(a,b),用于生成一个指定范围内的整数。其中参数a是下限,参数b是上限,生成的随机数n:a=n=b。import random 2)导入Image,ImageDraw,ImageFont模块,用于生成图片和字体。Image模块创建一个可用来对image进行操作的对象,对所有即将使用ImageDraw中操作的图片都要先进行这个对象的创建。ImageFont模块创建字体对象给ImageDraw中的text函数使用。这里需要首先安装Pillow(基于Python的图像库)。具体导入步骤可以
3、参考前面章节。如图6-14所示。然后在通过PIL导入Image,ImageDraw,ImageFont。from PIL import Image,ImageDraw,ImageFont图6-14 安装Pillow(3)定义图形验证码的背景图片。使用Image类实例化一个长为200px,宽为50px,基于RGB(200,220,210)颜色的图片。image=Image.new(mode=RGB,size=(200,50),color=(200,220,210)(4)Draw类实例化一支画笔,用于是实现在背景图片之上实现验证码的文字内容。image表示作用于的图片实例,mode=RGB表示采用
4、的配色方案。draw_brush=ImageDraw.Draw(image,mode=RGB)(5)定义在图形验证码中要使用的字体规格。注意:truetype方法中使用的字体名称一定要小写,不然会报错。arial.ttf表示字体风格,28表示字体大小。character_font=ImageFont.truetype(arial.ttf,28)(6)使用for循环和range(7)实现7次循环。循环体中使用random.choice方法随机选择其中生成的ASCII码为65-90的英文字母和0-9的数字,并分别使用chr和str方法将其转换为字符和字符串。random.randint方法将在每次
5、循环过程中随机生成一种字体颜色。最后使用draw_brush的text方法实现字体的间隔为i*30px,纵向为0px,字体颜色和字体大小。for i in range(7):character=random.choice(chr(random.randint(65,90),str(random.randint(0,9)character_color=(random.randint(0,255),random.randint(0,255),random.randint(0,255)draw_brush.text(i*30,0,character,character_color,font=char
6、acter_font)(7)使用with open把生成的图片保存为test.png格式。“test.png”表示当前目录中要写入的文件名称,如果没有将创建一个。“wb”表示将以二进制的方式写入该文件。因为保存的是一张图片,所以使用二进制的方式写入。接着使用image的save方法将该图片以“png”的格式保存。with open(test.png,wb)as f:image.save(f,format=png)(8)运行结果如图6-15所示。图6-15 图形验证码完整代码如下。import randomfrom PIL import Image,ImageDraw,ImageFontimag
7、e=Image.new(mode=RGB,size=(200,40),color=(200,220,210)draw_brush=ImageDraw.Draw(image,mode=RGB)character_font=ImageFont.truetype(arial.ttf,28)for i in range(7):character=random.choice(chr(random.randint(65,90),str(random.randint(0,9)character_color=(random.randint(0,255),random.randint(0,255),random
8、.randint(0,255)draw_brush.text(i*30,0,character,character_color,font=character_font)with open(test.png,wb)as f:image.save(f,format=png)到此,生成一个只有数字和字母的图形验证码。该验证码的特点为:字体统一为“arial”,英文字母均为大写,字体之间的间隔也是固定的30px,每个字体的颜色是随机的。之后将是用tesserocr针对图形验证码进行解析操作。6.1.6 tesserocr的基本用法【实例6-2】结合前面生成的图形验证码,这里将通过导入tesserocr
9、和PIL的Image实现一个基本图形验证码解析。具体步骤介绍如下:1)导入tesserocr和PIL的Image用于图像解析。import tesserocrfrom PIL import Image2)使用Image的open方法打开指定test.png图片,该方法返回一个图像实例,并将其赋值给变量image_to_parse。image_to_parse=Image.open(test.png)3)使用tesserocr的image_to_text方法对该图像实例进行解析,该方法返回文本内容,并将其赋值给变量text_result。如果安装的是Anaconda的Python,这里会报错,如
10、图6-16所示。错误原因是在E:anacondainstallation中没有找到有效的tessdata。因此,需要将Tesseract-OCRtessdata文件夹复制到E:anacondainstallation中(如果没有该文件夹则创建一个,这是在安装anaconda时让用户自定义的文件夹)即可。text_result=tesserocr.image_to_text(image_to_parse)图6-16 tesserocr使用的问题print(text_result)运行结果显示:7U4J3986.1.7 任务实现使用tesserocr解析自定义图形验证码【实例6-2】结合前面生成的
11、图形验证码,这里将通过导入tesserocr和PIL的Image实现一个基本图形验证码解析。具体步骤介绍如下:1)导入tesserocr和PIL的Image用于图像解析。import tesserocrfrom PIL import Image2)使用Image的open方法打开指定test.png图片,该方法返回一个图像实例,并将其赋值给变量image_to_parse。image_to_parse=Image.open(test.png)在了解了tesserocr的基本用法之后,现在,再找一个相对复杂的图形验证码。该图形验证码具有点状和线状的干燥图像。然后再使用上述代码运行一次,如图6-1
12、7所示。图6-17 带噪点的图形验证码运行结果显示:FEZJDQ这时会发现运行的结果并不是上面生成的验证码。这是怎么回事呢?这就是前面提到的二值化,图像降噪,字符分割和特征匹配等内容了。通过观察该图形验证码,发现出现偏差应该是由于加上了干扰噪音图像的原因,所以得到了错误的结果。【实例6-3】这里将借助灰度图、二值化和图像降噪等方式,通过设定阈值优化处理结果。1)使用Image对象的convert方法,并传入参数L,目的是将该图片进行灰度化,然后使用show方法将其显示。image_to_convert=image_to_parse.convert(L)image_to_convert.show
13、()运行结果如图6-18所示。图6-18 图形验证码灰度化 2)在灰度图上,部分色彩是介于白色跟黑色之间,所以通过设置阈值的方法,把这些中间色彩全部转换成黑色跟白色。因此,通过convert方法传入参数1将灰度图像进行二值化,此时的阈值默认为127。二值化是指将图像上的像素点的灰度值设置为0或255,也就是将整个图片呈现出明显的只有黑和百的视觉效果。image_to_convert=image_to_parse.convert(1)image_to_convert.show()运行结果如图6-19所示。图6-19 图形验证码二值化 3)经过不断地调试,最终设定一个比较合适的阈值threshol
14、d为50,并通过循环,将小于和大于该阈值的数据分别用0和1存入列表chart中,通过列表数据将图像转换成二进制,1表示白色,0就是黑色。然后,使用point方法根据chart的数据把图像做二值化处理。threshold=50chart=for i in range(256):if i threshold:chart.append(0)else:chart.append(1)image_for_threshold=image_to_convert.point(chart,1)image_for_threshold.show()运行结果如图6-20所示。图6-20 图形验证码处理结果 4)使用tesserocr的image_to_text方法将经过二值化处理后的数据文本化并输出。text_result=tesserocr.image_to_text(image_for_threshold)print(text_result)运行结果显示:LDZ到此,成功使用tesserocr解析了图形验证码中存在的一些干扰因素,提高了图像识别命中率。