Python爬虫之点触验证码的识别

点触验证码的识别

除了极验验证码,还有另一种常见且应用广泛的验证码,即点触验证码。

可能你对这个名字比较陌生,但是肯定见过类似的验证码,比如 12306 就是典型的点触验证码。

直接点击图中符合要求的图。所有答案均正确,验证才会成功。如果有一个答案错误,验证就会失败。这种验证码就称为点触验证码。

还有一个专门提供点触验证码服务的站点 TouClick,其官方网站为 https://www.touclick.com/。本节就以 TouClick 为例讲解此类验证码的识别过程。

1. 本节目标

我们的目标是用程序来识别并通过点触验证码的验证。

2. 准备工作

我们使用的 Python 库是 Selenium,使用的浏览器为 Chrome。请确保已经正确安装好 Selenium 库、Chrome 浏览器,并配置好 ChromeDriver,相关流程可以参考第 1 章的说明。

3. 了解点触验证码

TouClick 官方网站的验证码样式:

与 12306 站点相似,不过这次是点击图片中的文字而非图片。点触验证码有很多种,它们的交互形式略有不同,但其基本原理都是类似的。

接下来,我们统一实现此类点触验证码的识别过程。

4. 识别思路

如果依靠图像识别点触验证码,则识别难度非常大。例如,12306 的识别难点有两点,第一点是文字识别。

点击图中所有漏斗,“漏斗” 二字经过变形、放缩、模糊处理,如果要借助前面的 OCR 技术来识别,识别的精准度会大打折扣,甚至得不到任何结果。

第二点是图像的识别。我们需要将图像重新转化文字,可以借助各种识图接口,但识别的准确率非常低,经常会出现匹配不正确或无法匹配的情况。而且图片清晰度不够,识别难度会更大,更何况需要同时正确识别八张图片,验证才能通过。

综上所述,此种方法基本是不可行的。

我们再以 TouClick 为例。

我们需要从这幅图片中识别出 “植株” 二字,但是图片背景或多或少会有干扰,导致 OCR 几乎不会识别出结果。如果直接识别白色的文字不就好了吗?但是如果换一张验证码呢?文字颜色就又不同了,因此此方法是不可行的。

这张验证码图片的文字又变成了蓝色,而且还又有白色阴影,识别的难度又会大大增加。

这张验证码图片的文字变成了蓝色,有白色阴影,识别的难度会大大增加。

那么,此类验证码该如何识别?互联网上有很多验证码服务平台,平台 7×24 小时提供验证码识别服务,一张图片几秒就会获得识别结果,准确率可达 90% 以上。

我个人比较推荐的一个平台是超级鹰,其官网为 超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大。其提供的服务种类非常广泛,可识别的验证码类型非常多,其中就包括点触验证码。

超级鹰平台同样支持简单的图形验证码识别。如果 OCR 识别有难度,同样可以用本节介绍的方法借助此平台来识别。超级鹰平台提供了如下一些服务。

  • 英文数字:提供最多 20 位英文数字的混合识别

  • 中文汉字:提供最多 7 个汉字的识别

  • 纯英文:提供最多 12 位的英文的识别

  • 纯数字:提供最多 11 位的数字的识别

  • 任意特殊字符:提供不定长汉字英文数字、拼音首字母、计算题、成语混合、 集装箱号等字符的识别

  • 坐标选择识别:如复杂计算题、选择题四选一、问答题、点击相同的字、物品、动物等返回多个坐标的识别

具体如有变动以官网为准:验证码类型与价格表-超级鹰验证码识别。

这里需要处理的就是坐标多选识别的情况。我们先将验证码图片提交给平台,平台会返回识别结果在图片中的坐标位置,然后我们再解析坐标模拟点击。

下面我们就用程序来实现。

5. 注册账号

先注册超级鹰账号并申请软件 ID,注册页面链接为 用户注册-超级鹰验证码识别代答题平台。在后台开发商中心添加软件 ID。最后充值一些题分,充值多少可以根据价格和识别量自行决定。

6. 获取 API

在官方网站下载对应的 Python API,链接为:Python语言Demo下载-超级鹰验证码识别API接口。此 API 是 Python 2 版本的,是用 requests 库来实现的。我们可以简单更改几个地方,即可将其修改为 Python 3 版本。

修改之后的 API 如下所示:

import requests
from hashlib import md5
​
class Chaojiying(object):
​def __init__(self, username, password, soft_id):self.username = usernameself.password = md5(password.encode('utf-8')).hexdigest()self.soft_id = soft_idself.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 post_pic(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 report_error(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()

这里定义了一个 Chaojiying 类,其构造函数接收三个参数,分别是超级鹰的用户名、密码以及软件 ID,保存以备使用。

最重要的一个方法叫作 post_pic(),它需要传入图片对象和验证码类型的代号。该方法会将图片对象和相关信息发给超级鹰的后台进行识别,然后将识别成功的 JSON 返回。

另一个方法叫作 report_error(),它是发生错误的时候的回调。如果验证码识别错误,调用此方法会返回相应的题分。

接下来,以 TouClick 的官网为例,来演示点触验证码的识别过程,链接为 http://admin.touclick.com/。

7. 初始化

首先初始化一些变量,如 WebDriver、Chaojiying 对象等,代码实现如下所示:

EMAIL = 'cqc@cuiqingcai.com'
PASSWORD = ''
# 超级鹰用户名、密码、软件 ID、验证码类型
CHAOJIYING_USERNAME = 'Germey'
CHAOJIYING_PASSWORD = ''
CHAOJIYING_SOFT_ID = 893590
CHAOJIYING_KIND = 9102
​
class CrackTouClick():def __init__(self):self.url = 'http://admin.touclick.com/login.html'self.browser = webdriver.Chrome()self.wait = WebDriverWait(self.browser, 20)self.email = EMAILself.password = PASSWORDself.chaojiying = Chaojiying(CHAOJIYING_USERNAME, CHAOJIYING_PASSWORD, CHAOJIYING_SOFT_ID)

这里的账号和密码请自行修改。

8. 获取验证码

接下来的第一步就是完善相关表单,模拟点击呼出验证码,代码实现如下所示:

def open(self):"""打开网页输入用户名密码:return: None"""self.browser.get(self.url)email = self.wait.until(EC.presence_of_element_located((By.ID, 'email')))password = self.wait.until(EC.presence_of_element_located((By.ID, 'password')))email.send_keys(self.email)password.send_keys(self.password)def get_touclick_button(self):"""获取初始验证按钮:return:"""button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'touclick-hod-wrap')))return button

open() 方法负责填写表单,get_touclick_button() 方法获取验证码按钮,之后触发点击即可。

接下来,类似极验验证码图像获取一样,获取验证码图片的位置和大小,从网页截图里截取相应的验证码图片,代码实现如下所示:

def get_touclick_element(self):"""获取验证图片对象:return: 图片对象"""element = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'touclick-pub-content')))return element
​
def get_position(self):"""获取验证码位置:return: 验证码位置元组"""element = self.get_touclick_element()time.sleep(2)location = element.locationsize = element.sizetop, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size['width']return (top, bottom, left, right)
​
def get_screenshot(self):"""获取网页截图:return: 截图对象"""screenshot = self.browser.get_screenshot_as_png()screenshot = Image.open(BytesIO(screenshot))return screenshot
​
def get_touclick_image(self, name='captcha.png'):"""获取验证码图片:return: 图片对象"""top, bottom, left, right = self.get_position()print(' 验证码位置 ', top, bottom, left, right)screenshot = self.get_screenshot()captcha = screenshot.crop((left, top, right, bottom))return captcha

get_touclick_image() 方法即为从网页截图中截取对应的验证码图片,其中验证码图片的相对位置坐标由 get_position() 方法返回得到。最后我们得到的是 Image 对象。

9. 识别验证码

调用 Chaojiying 对象的 post_pic() 方法,即可把图片发送给超级鹰后台,这里发送的图像是字节流格式,代码实现如下所示:

image = self.get_touclick_image()
bytes_array = BytesIO()
image.save(bytes_array, format='PNG')
# 识别验证码
result = self.chaojiying.post_pic(bytes_array.getvalue(), CHAOJIYING_KIND)
print(result)

运行之后,result 变量就是超级鹰后台的识别结果。可能运行需要等待几秒。

返回的结果是一个 JSON。如果识别成功,典型的返回结果如下所示:

{'err_no': 0, 'err_str': 'OK', 'pic_id': '6002001380949200001', 'pic_str': '132,127|56,77', 'md5': '1f8e1d4bef8b11484cb1f1f34299865b'}

其中,pic_str 就是识别的文字的坐标,是以字符串形式返回的,每个坐标都以 | 分隔。接下来我们只需要将其解析,然后模拟点击,代码实现如下所示:

def get_points(self, captcha_result):"""解析识别结果:param captcha_result: 识别结果:return: 转化后的结果"""groups = captcha_result.get('pic_str').split('|')locations = [[int(number) for number in group.split(',')] for group in groups]return locations
​
def touch_click_words(self, locations):"""点击验证图片:param locations: 点击位置:return: None"""for location in locations:print(location)ActionChains(self.browser).move_to_element_with_offset(self.get_touclick_element(), location[0], location[1]).click().perform()time.sleep(1)

这里用 get_points() 方法将识别结果变成列表的形式。touch_click_words() 方法则通过调用 move_to_element_with_offset() 方法依次传入解析后的坐标,点击即可。

这样我们就模拟完成坐标的点选,运行效果。

最后点击提交验证的按钮,等待验证通过,再点击登录按钮即可成功登录。后续实现在此不再赘述。

这样我们就借助在线验证码平台完成了点触验证码的识别。此方法是一种通用方法,我们也可以用此方法来识别 12306 等验证码。

10. 结语

本节我们通过在线打码平台辅助完成了验证码的识别。这种识别方法非常强大,几乎任意的验证码都可以识别。如果遇到难题,借助打码平台无疑是一个极佳的选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/488483.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

PLC_博图系列☞基本指令“赋值取反”

PLC_博图系列☞基本指令“赋值取反” 文章目录 PLC_博图系列☞基本指令“赋值取反”背景介绍/:赋值取反说明参数示例 关键字: PLC、 西门子、 博图、 Siemens 、 赋值取反 背景介绍 这是一篇关于PLC编程的文章,特别是关于西门子的博图软…

震撼升级!24版短视频矩阵全开源码,打造您的AI智能剪辑帝国

应用介绍 私信我拿演示后台 亲爱的创业者和内容创作者们,我们为您带来了业界颠覆性的全新产品——24版短视频矩阵全开源码。这不仅是一次技术的飞跃,更是您在短视频领域实现高效创作与规模化运营的一把利剑。 此次升级,我们彻底打破常规&…

Docker 第十九章 : 阿里云个人镜像仓使用

Docker 第十九章 : 阿里云个人镜像仓使用 本章知识点: 如何创建镜像库,如何设置密码,如何登录与退出个人镜像仓,如何本地打镜像,如何将本地镜像推送到个人镜像库。 背景 在项目YapiDocker部署中,因读取mongo:latest 版本不一致,导致后续执行步骤的异常。遇到此场景…

责任链模式与spring容器的搭配应用

背景 有个需求,原先只涉及到一种A情况设备的筛选,每次筛选会经过多个流程,比如先a功能,a功能通过再筛选b功能,然后再筛选c功能,以此类推。现在新增了另外一种B情况的筛选,B情况同样需要A情况的筛…

2024年机械制造业行业转型展望

行业变革中的挑战与机遇 2024年将是全球工业格局发生重大变化的一年。CADENAS着眼于最重要的五大主题:数字化转型、技能短缺、供应链、可持续发展和人工智能(AI)。这些领域为全球公司带来了挑战和机遇。 数字化转型:通向未来之路…

如何让电脑待机而wifi不关的操作方法!!

1、一台电脑如果一天不关机,大约消耗0.3度电。 一般一台电脑的功耗约为250-400W(台式机)。 一台电脑每月的耗电量:如果是每小时300W每天10小时每月30天90KW,即90千瓦时的电。 这只是保守估计。 2、使用完毕后正常关闭…

一次有趣的nginx Tcp4层代理转发的试验

nginx主配置文件添加配置: stream {log_format proxy $remote_addr [$time_local] $protocol status:$status bytes_sent:$bytes_sent bytes_received:$bytes_received $session_time upstream_addr:"$upstream_addr" "$upstream_bytes_sent" …

【Java EE初阶二十四】servlet的深入理解

1. Servlet API 的学习 下面主要学习这三个类,就已经可以完成 Servlet 的大部分开发了; 1. Httpservlet 2. HttpServletRequest 3. HttpServletResponse 2. Httpservlet的学习 2.1 Httpservlet在tomcat的工作原理 写一个 Servlet 代码,往往都…

代码随想录刷题39,40天|62.不同路径

62.不同路径 想要求dp[i][j],只能有两个方向来推导出来,即dp[i - 1][j] 和 dp[i][j - 1]。 此时在回顾一下 dp[i - 1][j] 表示啥,是从(0, 0)的位置到(i - 1, j)有几条路径,dp[i][j - 1]同理。 那么很自然,dp[i][j] …

ShardingSphere5.x 分库分表

一、shardingSphere介绍 1、官网:Apache ShardingSphere 2、开发文档: 概览 :: ShardingSphere 3、shardingsphere-jdbc ShardingSphere-JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库&#x…

2024022402-数据库恢复技术

数据库恢复技术 什么是事务 事务(Transaction)是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位 事务和程序是两个概念 在关系数据库中,一个事务可以是一条SQL语句,一组SQL语…

无公网IP情况下如何远程查看本地群晖NAS存储的文件资源

文章目录 前言本教程解决的问题是:按照本教程方法操作后,达到的效果是前排提醒: 1. 搭建群晖虚拟机1.1 下载黑群晖文件vmvare虚拟机安装包1.2 安装VMware虚拟机:1.3 解压黑群晖虚拟机文件1.4 虚拟机初始化1.5 没有搜索到黑群晖的解…