接上条 Python反爬机制-验证码(一)https://developer.aliyun.com/article/1617995
2. 第三方验证码识别
针对OCR识别率和准确度不高的缺点,使用第三方验证码识别平台是一个不错的选择,不仅可以解决验证码识别率低低问题,还可以提高验证码识别的准确度。第三方平台识别验证码非常简单,平台提供了完善的API接口,根据平台对应的开发文档即可完成快速开发的需求,但每次验证码成功识别后平台会收取少量费用。
验证码识别平台一般分为两种,分别是打码平台和AI开发者平台。打码平台主要是由在线人员进行验证码的识别工作,然后在较短的时间内返回结果。AI开发者平台主要是由人工智能来进行识别。例如,百度AI。
下面以打码平台为例,演示验证码识别的具体过程。
(1)在浏览器中打开打码平台网页(http://www.chaojiying.com/),并且单击首页的“用户注册”按钮,如图所示:
(2) 然后在用户中心页面中填写注册账号的基本信息。如下图:
说 明
账号注册完成以后可以联系平台的客服人员,申请免费测试的题分。
(3) 账号注册完成以后,在网页的顶部导航栏中选择“开发文档”,然后在常用开发语言示例下载中选择“Python“语言,如下图所示:
(4) 在Python语音Demo下载页面中,查看注意事项,然后单击“点击这里下载”超链接即可下载示例代码,如图所示:
(5)平台提供的示例代码中,已经将所有需要用到的功能代码进行了封装处理,封装的代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 10:01 AM
# 文件 :平台提供识别封装代码.py
# IDE :PyCharm
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/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"
}
def PostPic(self, im, codetype):
"""
im: 图片字节
codetype: 题目类型 参考 http://www.chaojiying.com/price.html
"""
params = {
'codetype': codetype,
}
params.update(self.base_params) # 更新表单参数
files = {
'userfile': ('code2.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()
if __name__ == '__main__':
#用户中心>>软件ID 生成一个替换 96001
chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '928939')
im = open('a.jpg', 'rb').read() #本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
#1902 验证码类型 官方网站>>价格体系 3.4+版 print 后要加()
print(chaojiying.PostPic(im, 1902))
(6)使用平台示例代码中所提供的验证码图片,运行以上示例代码,运行结果如下:
{
'err_no': 0, 'err_str': 'OK', 'pic_id': '9168810337948200001', 'pic_str': '7261', 'md5': '345c80a5dba345c219cc8893f19b496c'}
Process finished with exit code 0
说 明
程序运行结果中pic_str对应的值为返回的验证码识别信息。
在发送识别验证码的网络请求时,代码中的“1902”表示验证码的类型,该平台所支持的常用验证码类型如下表:
常用验证码类型
复杂计算题
说 明
表中之列出了比较常用的验证码识别类型,详细内容可查验证码平台官网
- 滑动拼图验证码
滑动拼图验证码是在滑动验证码的基础上增加了滑动距离的校验,用户需要将图形滑块滑动至主图空缺滑块的位置,才能通过校验。下面通过案例测试,实现滑动拼图验证码的自动校验。测试网页地址:http://sck.rjkflm.com:666/spider/jgsaw/
(1) 使用浏览器打开测试页的地址,将显示如图所示的滑动拼图验证码。
(2) 打开浏览器开发者工具,单击按钮滑块,然后在HTML代码中依次获取“按钮滑块”“图形滑块”以及“空缺滑块”所对应的HTML代码标签所在的位置。
# 图形滑块
<div class="verify" style="display: block; top: 30.2081px; background-position: -173.893px -30.2081px; left: 10px;"></div>
# 按钮滑块
<span class="swiper" style="left: 0px;"></span>
(3)验证成功后的按钮滑块”“图形滑块”以及“空缺滑块”位置变化如下所示
# 图形滑块
<div class="verified" style="display: block; left: 173.893px; top: 30.2081px;"></div>
# 按钮滑块
<span class="swiper" style="left: 0px;"></span>
(4) 通过按钮滑块的left值可以确认需要滑动的距离,接下来只需要使用selenium框架模拟滑动的工作即可。实现代码如下:
#_*_coding:utf-8_*_
# 作者 :liuxiaowei
# 创建时间 :2/16/22 5:19 PM
# 文件 :使用selenium框架模拟滑动图块.py
# IDE :PyCharm
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])
# 获取图形滑块left值
verify_left =float(re.findall('left: (.*?)px;',verify_style)[0])
action.move_by_offset(verified_left-verify_left,0) # 滑动指定距离
action.release().perform()
# 松开鼠标
程序运行如下图显示:
总 结