Python网络爬虫之如何用代码识别图片验证码

验证码

当我们在爬取某些网站的时候,对于一些频繁请求,网站会识别你是机器还是人。如果是机器,直接不允许你访问这个网站了,直接返回404或者禁止访问。


最常见的方式就是验证码。验证码的主要功能就是区分当前访问网站的是人还是代码。越难识别或者越模糊的验证码区分能力却强。网站想方设法的搞一些手段来对付技术,就是想让服务器不用承受代码大量访问的压力,这样就能够为正常用户提供流畅的服务了。


但是,技术又能对付人们的想法。一来一去,就有了各种各样的变态验证码,也有了各种各样的应对方式。


常见的验证码有这么几种:

  • 图像验证
  • 语音验证
  • 短信验证
  • 极验验证
  • 点击验证

如何识别图像验证码

来看看这些图片验证码:

Python网络爬虫之如何用代码识别图片验证码

这些验证码大多是数字和字母组成,然后在此之上再添加一些模糊的噪点或者横线竖线,或者把这些字符扭曲一下,增加识别难度。


接下来我们思考一下,我们要识别这类验证码要怎么做呢?

首先要处理一下验证码图片,什么乱七八糟的噪点都尽量把它们去掉,让图片尽量黑白,尽量只剩下字符本身,然后再用 python 强大的 OCR 工具:

<code>Python-tesseract/<code>

来识别我们优化好的图片,这样正确率就会大大的提高。


我们用 python 搞几张识别难度不同的验证码:

第一张

Python网络爬虫之如何用代码识别图片验证码

难度系数: ★,一颗星

第二张

Python网络爬虫之如何用代码识别图片验证码

难度系数: ★★,两颗星

第三张

Python网络爬虫之如何用代码识别图片验证码

难度系数: ★★★,三颗星

第四张

Python网络爬虫之如何用代码识别图片验证码

难度系数: ★★★★,四颗星

第五张

Python网络爬虫之如何用代码识别图片验证码

难度系数 : ★★★★★,五颗星


先对第一张进行识别。第一张看起来比较清晰,识别起来没有难度。


先安装一下 pytesseract :

<code>pip install pytesseract/<code>

接着安装一下 tesseract-ocr:

如果是 ubuntu 系统可以直接使用如下命令安装:

<code>sudo apt install tesseract-ocr/<code>

如果是 win 系统自行百度一下安装 tesseract-ocr 以及环境变量配置。


完了之后就导入相关模块到代码文件中:

<code>try:
from PIL import Image
except ImportError:
import Image
import pytesseract/<code>

接着打开第一张图片,使用 pytesseract 识别,打印出结果:

<code>captcha = Image.open("captcha1.png")
result = pytesseract.image_to_string(captcha)
print(result)/<code>

结果:

Python网络爬虫之如何用代码识别图片验证码

识别成功!


接着来识别第 2 张:

Python网络爬虫之如何用代码识别图片验证码

<code>captcha = Image.open("claptcha2.png")
result = pytesseract.image_to_string(captcha)
print(result)/<code>

结果是

Python网络爬虫之如何用代码识别图片验证码


1924,结果有误!pytesseract 准确率没那么高,没办法识别太多噪点的图片。如果这个图片再加上一点彩色背景如下图:

Python网络爬虫之如何用代码识别图片验证码

对 pytesseract 来说更有难度。

所以我们先对这张图片灰度处理一下:

<code>captcha = Image.open("captcha2.png")
result = captcha.convert('L')
result.show()/<code>

图片就变成灰了:

Python网络爬虫之如何用代码识别图片验证码


虽然灰了,但是还不够。除了处理灰度还需要对其进行“二值化”:

<code>def convert_img(img,threshold):
img = img.convert("L") # 处理灰度
pixels = img.load()
for x in range(img.width):
for y in range(img.height):
if pixels[x, y] > threshold:
pixels[x, y] = 255
else:
pixels[x, y] = 0
return img/<code>

调用一下:

<code>convert_img(captcha,150)/<code>

图片就变成了:


Python网络爬虫之如何用代码识别图片验证码

非常清晰!

这时候对这张图片识别一下:

<code># 识别一下
result = pytesseract.image_to_string(result)
print(result)/<code>

成功识别!

Python网络爬虫之如何用代码识别图片验证码


Python网络爬虫之如何用代码识别图片验证码

这时候直接去识别是识别不出来的。所以还是老办法,先处理灰度,再进行“二值化”。这次再降一下噪:

<code>data = img.getdata()
w,h = img.size
count = 0
for x in range(1,h-1):
for y in range(1, h - 1):
# 找出各个像素方向
mid_pixel = data[w * y + x]
if mid_pixel == 0:
top_pixel = data[w * (y - 1) + x]
left_pixel = data[w * y + (x - 1)]
down_pixel = data[w * (y + 1) + x]
right_pixel = data[w * y + (x + 1)]

if top_pixel == 0:
count += 1
if left_pixel == 0:
count += 1
if down_pixel == 0:
count += 1
if right_pixel == 0:
count += 1
if count > 4:
img.putpixel((x, y), 0)/<code>

图片变成这样了:


Python网络爬虫之如何用代码识别图片验证码

再识别一下:

Python网络爬虫之如何用代码识别图片验证码


不过,pytesseract 不是万能的,对于稍微复杂一点的就识别不出来了。至于这张:

Python网络爬虫之如何用代码识别图片验证码

我们肉眼都很难看出它是 1l1l0oO0,更不要说用代码去识别了,所以 pytesseract 也识别不了。


对于一些简单的验证码,使用 pytesseract 还是可以的。如果我们想提高 pytesseract 识别率,还可以去搞些图片去训练一下 tesseract-ocr。这样,当我们遇到一些登录需要验证码的网站时,直接引入本文识别验证码的方法就可以继续爬数据了。


分享到:


相關文章: