验证码是许多网站都采取的反爬虫机制,随着技术的发展,验证码出现了各种各样的形态。从一开始的几个数字,发展到随机添加几个英文字母以及混淆曲线、彩色斑点、滑动拼图等,形态越来越复杂。本篇博文将介绍如何使用 OCR 技术实现字符验证码的识别、如何使用第三方验证码识别平台识别验证码以及滑动拼图验证码的校验工作。
字符验证码的特点就是验证码中包含数字、字母或者掺杂着斑点与混淆曲线的图片验证码。识别此类验证码,首先需要找到验证码图片在网页 HTML 代码中的位置,然后将验证码下载,最后再通过 OCR 技术进行验证码的识别工作。
Tesseract-OCR 是一个免费、开源的 OCR 引擎,通过该引擎可以识别图片中的验证码,搭建 OCR 的具体步骤如下:
(1) 点击 此处 打开 Tesseract-OCR下载地址,然后选择与自己操作系统匹配的版本(博主电脑为 Windows 64位操作系统),如下图所示。
(2) Tesseract-OCR 文件下载完成后,默认安装即可。
(3) 找到 Tesseract-OCR 的安装路径(默认为 C:\Program Files\Tesseract-OCR\tessdata),然后将安装路径添加至系统环境变量中,首先右键单击 此电脑
依次选择属性 ⇒ 高级系统设置 ⇒ 环境变量,然后在上面的用户变量中单击 新建
,在弹出的 新建用户变量
窗口中设置变量名与变量值,如下图所示。
说明:Tesseract-OCR 环境变量配置完成以后,请重新启动 Pycharm 开发工具。
(4) 接下来需要安装 tesserocr 模块,安装命令如下:
pip install tesserocr # 读者可自行添加镜像加快下载速度
如果使用的是 Anaconda 并在安装 tesserocr 模块时出现了错误,可以使用如下命令:
conda install -c simonflueckiger tesserocr
如果以上两种安装 tesserocr 模块的方式都遇到问题时,可以从下面百度网盘中下载 tesserocr-2.4.0-cp37-cp37m-win_amd64.whl,接着启动 命令提示符窗口
,然后通过 pip install tesserocr-2.4.0-cp37-cp37m-win_amd64.whl
安装 tesserocr 模块。
链接:https://pan.baidu.com/s/1uE0BwOnGkxzzXjMqyKtCnA
提取码:i19b
复制这段内容后打开百度网盘手机App,操作更方便哦--来自百度网盘超级会员V6的分享
以下面地址对应的网页为例,下载网页中的验证码图片,具体步骤如下:
测试网页地址:https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx
(1)使用浏览器打开测试网页的地址,将显示下图所示的字符验证码。
(2) 打开浏览器开发者工具,然后在 HTML 代码中获取验证码图片所在的位置,如下图所示。
(3) 对目标网页发送网络请求,并在返回的 HTML 代码中获取图片的下载地址,然后下载验证码图片。代码如下:
# -*- coding: UTF-8 -*-
"""
@author:AmoXiang
@file:1.download_pic.py
@time:2021/01/19
"""
import requests # 导入网络请求模块
import urllib.request
from bs4 import BeautifulSoup # 导入解析HTML的模块
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"}
# 发送网络请求
url = "https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx"
response = requests.get(url=url, headers=headers)
html = BeautifulSoup(response.text, "lxml")
img_src = html.select("#imgCode")[0].attrs["src"] # 解析图片src
# 组合验证码图片请求地址
img_url = "https://so.gushiwen.cn/" + img_src
# 下载并设置图片名称
urllib.request.urlretrieve(img_url, "code.png")
验证码下载完成以后,如果没有安装 pillow 模块,需要通过 pip install pillow
命令安装一下,然后导入 tesserocr 与 Image 模块,再通过 Image.open() 方法打开验证码图片,接着通过 tesserocr.image_to_text() 函数识别图片中的验证码信息即可。示例代码如下:
# -*- coding: UTF-8 -*-
"""
@author:AmoXiang
@file:demo.py
@time:2021/01/19
"""
import tesserocr # 导入tesserocr模块
from PIL import Image # 导入图像处理模块
img = Image.open("code.png") # 打开验证码图片
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print(f"验证码为: {code}")
博主重新生成了一张验证码图片,程序运行结果如下:
OCR 的识别技术虽然很强大,但是并不是所有的验证码都可以这么轻松地识别出来,例如下图所示的验证码中就会掺杂着许多干扰线条,那么在识别这样的验证码信息时,就需要对验证码图片进行相应的处理并识别。
如果直接通过 OCR 识别,识别结果将会受到干扰线的影响。下面通过 OCR 直接识别测试一下,识别代码与效果如下:
import tesserocr # 导入tesserocr模块
from PIL import Image # 导入图像处理模块
img = Image.open("code.png") # 打开验证码图片
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print(f"验证码为: {code}")
程序运行结果如下:
通过以上测试可以发现,直接通过 OCR 技术识别后为空,遇到此类情况首先可以将彩色的验证码图片转换为灰度图片再测试一下。示例代码如下:
import tesserocr
from PIL import Image
img = Image.open("code.png")
img = img.convert("L")
t = 155
table = []
for i in range(256):
if i < t:
table.append(0)
else:
table.append(1)
img = img.point(table, "1")
img.show()
code = tesserocr.image_to_text(img) # 将图片中的验证码转换为文本
print(f"验证码为: {code}")
程序运行后将自动显示下图所示二值化处理后的验证码图片。
控制台中所识别的验证码如下:
虽然 OCR 可以识别验证码图片中的验证码信息,但是识别效率与准确度不高是 OCR 的缺点。所以使用第三方验证码识别平台是一个不错的选择,不仅可以解决验证码识别效率低的问题,还可以提高验证码识别的准确度。使用第三方平台识别验证码是非常简单的,平台提供了完善的 API 接口,根据平台对应的开发文档即可完成快速开发的需求,但每次验证码成功识别后平台会收取少量的费用。
验证码识别平台一般分为两种,分别是打码平台和 AI 开发者平台。打码平台主要是由在线人员进行验证码的识别工作,然后在较短的时间内返回结果。AI 开发者平台主要是由人工智能来进行识别,例如,百度 AI。
下面以打码平台为例,演示验证码识别的具体过程。
(1) 点击 此处 在浏览器中打开打码平台网页,并且单击首页的 用户注册
按钮,如下图所示。
(2) 然后在用户中心的页面中填写注册账号的基本信息,如下图所示。
说明:账号注册完成以后可以联系平台的客服人员,申请免费测试的题分。
(3) 账号注册完成以后,在网页的顶部导航栏中选择 开发文档
,然后在常用开发语言示例下载中选择 Python
语言,如下图所示。
(4) 在 Python 语言 Demo下载页面中,查看注意事项,然后单击 点击这里下载
超链接即可下载示例代码,如下图所示。
(5) 平台提供的示例代码中,已经将所有需要用到的功能代码进行了封装处理,封装后的代码如下:
# -*- coding: UTF-8 -*-
"""
@author:AmoXiang
@file:2.chaojiying.py
@time:2021/01/19
"""
import requests # 网络请求模块
from hashlib import md5 # 加密
class Chaojiying_Client(object):
def __init__(self, username, password, soft_id):
self.username = username # 自己注册的账号
password = password.encode('utf8') # 自己注册的密码
self.password = md5(password).hexdigest()
self.soft_id = soft_id # 软件ID
self.base_params = {
# 组合表单数据
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
# 请求头信息
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params) # 更新表单参数
files = {
'userfile': ('ccc.jpg', im)} # 上传验证码图片
r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
headers=self.headers)
return r.json() # 返回响应数据
def ReportError(self, im_id):
"""
im_id:报错题目的图片ID
"""
params = {
'id': im_id,
}
params.update(self.base_params)
r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
return r.json()
(6) 在已经确保用户名完成充值的情况下,填写必要参数,然后创建实例代码中的实例对象,实现验证码的识别工作。代码如下:
if __name__ == '__main__':
# 用户中心>>软件ID 生成一个替换 96001
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001')
im = open('a.jpg', 'rb').read() # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
# 1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
print(chaojiying.PostPic(im, 1902))
(7) 使用平台示例代码中所提供的验证码图片,运行以上示例代码,程序运行结果如下:
{'err_no': 0, 'err_str': 'OK', 'pic_id': '6129521154616800019',
'pic_str': '7261', 'md5': 'cc4e43a6905b3a447436b273a3ea121b'}
说明:程序运行结果中 pic_str 所对应的值为返回的验证码识别信息。
在发送识别验证码的网络请求时,代码中的 1902
表示验证码类型,该平台支持所有的常用验证码类型点击 此处 可进行查询。
滑动拼图验证码是在滑动验证码的基础上增加了滑动距离的校验,用户需要将图形滑块滑动至主图空缺滑块的位置,才能通过校验。下面以测试地址对应的网页为例,实现滑动拼图验证码的自动校验,具体步骤如下:
测试网页地址如下:
http://sck.rjkflm.com:666/spider/jigsaw/
(1) 使用浏览器打开测试网页的地址,将显示如下图所示的滑动拼图验证码。
(2) 打开浏览器开发者工具,单击按钮滑块,然后在 HTML 代码中依次获取 按钮滑块/图形滑块
以及 空缺滑块
所对应的 HTML 代码标签所在的位置,如下图所示。
(3) 拖动按钮滑块,完成滑动拼图验证码的校验,此时将显示如下图所示的 HTML 代码。
滑动的距离 = 空缺滑块到左侧的距离 - 圆形滑块到左侧的距离
(4) 通过按钮滑块的 left 值可以确认需要滑动的距离,接下来只需要使用 selenium 框架模拟滑动的工作即可。实现代码如下:
# -*- coding: UTF-8 -*-
"""
@author:AmoXiang
@file:demo3.py
@time:2021/01/19
"""
from selenium import webdriver # 导入webdriver
import re # 导入正则模块
driver = webdriver.Chrome() # 谷歌浏览器
driver.get('http://sck.rjkflm.com:666/spider/jigsaw/') # 启动网页
swiper = driver.find_element_by_xpath(
'/html/body/div/div[2]/div[2]/span[1]') # 获取按钮滑块
action = webdriver.ActionChains(driver) # 创建动作
action.click_and_hold(swiper).perform() # 单击并保证不松开
# 滑动0距离,不松手,不执行该动作无法获取图形滑块left值
action.move_by_offset(0, 0).perform()
# 获取图形滑块样式
verify_style = driver.find_element_by_xpath(
'/html/body/div/div[2]/div[1]/div[1]').get_attribute('style')
# 获取空缺滑块样式
verified_style = driver.find_element_by_xpath(
'/html/body/div/div[2]/div[1]/div[2]').get_attribute('style')
# 获取空缺滑块left值
verified_left = float(re.findall('left: (.*?)px;', verified_style)[0])
# print(verified_left)
# 获取图形滑块left值
verify_left = float(re.findall('left: (.*?)px;', verify_style)[0])
# print(verify_left)
action.move_by_offset(verified_left - verify_left, 0) # 滑动指定距离
action.release().perform() # 松开鼠标
感谢您阅读本篇博文,希望本文能成为您编程路上的领航者。祝您阅读愉快!
好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
如果我的博客对你有帮助、如果你喜欢我的博客内容,请点赞
、评论
、收藏
一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
编码不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注
我哦!