Python3爬虫关于识别点触点选验证码的实例讲解

上一节我们实现了极验验证码的识别,但是除了极验其实还有另一种常见的且应用广泛的验证码,比较有代表性的就是点触验证码。

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

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

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

1. 本节目标

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

2. 准备工作

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

3. 了解点触验证码

TouClick 官方网站的验证码样式如图 8-19 所示:

和 12306 站点有相似之处,不过这次是点击图片中的文字,不是图片了,另外还有各种形形色色的点触验证码,其交互形式可能略有不同,但基本原理都是类似的。

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

4. 识别思路

此种验证码的如果依靠图像识别的话识别难度非常之大。

例如就 12306 来说,其识别难点有两个点,第一点是文字识别,如图 8-20 所示:

如点击图中所有的漏斗,“漏斗”二字其实都经过变形、放缩、模糊处理了,如果要借助于前面我们讲的 OCR 技术来识别,识别的精准度会大打折扣,甚至得不到任何结果。第二点是图像的识别,我们需要将图像重新转化文字,可以借助于各种识图接口,可经我测试识别正确结果的准确率非常低,经常会出现匹配不正确或匹配不出结果的情况,而且图片本身的的清晰度也不够,所以识别难度会更大,更何况需要同时识别出八张图片的结果,且其中几个答案需要完全匹配正确才能验证通过,综合来看,此种方法基本是不可行的。

再拿 TouClick 来说,如图所示:

我们需要从这幅图片中识别出植株二字,但是图片的背景或多或少会有干扰,导致 OCR 几乎不会识别出结果,有人会说,直接识别白色的文字不就好了吗?但是如果换一张验证码呢?如图 8-22 所示:

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

那么此类验证码就没法解了吗?答案当然是有,靠什么?靠人。

靠人解决?那还要程序做什么?不要急,这里说的人并不是我们自己去解,在互联网上存在非常多的验证码服务平台,平台 7×24 小时提供验证码识别服务,一张图片几秒就会获得识别结果,准确率可达 90% 以上,但是就需要花点钱来购买服务了,毕竟平台都是需要盈利的,不过不用担心,识别一个验证码只需要几分钱。

在这里我个人比较推荐的一个平台是超级鹰。

其提供的服务种类非常广泛,可识别的验证码类型非常多,其中就包括此类点触验证码。

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

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

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

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

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

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

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

而本节我们需要解决的就是属于最后一类,坐标多选识别的情况,我们需要做的就是将验证码图片提交给平台,然后平台会返回识别结果在图片中的坐标位置,接下来我们再解析坐标模拟点击就好了。

原理非常简单,下面我们就来实际用程序来实验一下。

5. 注册账号

在开始之前,我们需要先注册一个超级鹰账号并申请一个软件ID,注册页面链接为:https://www.chaojiying.com/user/reg/,注册完成之后还需要在后台开发商中心添加一个软件ID,最后一件事就是充值一些题分,充值多少可以根据价格和识别量自行决定。

6. 获取API

做好上面的准备工作之后我们就可以开始用程序来对接验证码的识别了。

首先我们可以到官方网站下载对应的 Python API,链接为:https://www.chaojiying.com/api-14.html,但是此 API 是Python2 版本的,是用 Requests 库来实现的,我们可以简单更改几个地方即可将其修改为 Python3 版本。

修改之后的API如下:

import requests
from hashlib import md5
class Chaojiying(object):
    def __init__(self, username, password, soft_id):
        self.username = username
        self.password = md5(password.encode('utf-8')).hexdigest()
        self.soft_id = soft_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 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 = EMAIL
        self.password = PASSWORD
        self.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.location
    size = element.size
    top, 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': '1f8e1d4bef8b
11484cb1f1f34299865b'}

其中 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. 本节代码

本节代码地址为:https://github.com/Python3WebSpider/CrackTouClick

11. 结语

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

(0)

相关推荐

  • Python3爬虫中识别图形验证码的实例讲解

    本节我们首先来尝试识别最简单的一种验证码,图形验证码,这种验证码出现的最早,现在也很常见,一般是四位字母或者数字组成的,例如中国知网的注册页面就有类似的验证码,链接为:http://my.cnki.net/elibregister/commonRegister.aspx,页面: 表单的最后一项就是图形验证码,我们必须完全输入正确图中的字符才可以完成注册. 1.本节目标 本节我们就以知网的验证码为例,讲解一下利用 OCR 技术识别此种图形验证码的方法. 2. 准备工作 识别图形验证码需要的库有 T

  • Python3爬虫关于识别检验滑动验证码的实例

    上节我们了解了图形验证码的识别,简单的图形验证码我们可以直接利用 Tesserocr 来识别,但是近几年又出现了一些新型验证码,如滑动验证码,比较有代表性的就是极验验证码,它需要拖动拼合滑块才可以完成验证,相对图形验证码来说识别难度上升了几个等级,本节来讲解下极验验证码的识别过程. 1. 本节目标 本节我们的目标是用程序来识别并通过极验验证码的验证,其步骤有分析识别思路.识别缺口位置.生成滑块拖动路径,最后模拟实现滑块拼合通过验证. 2. 准备工作 本次我们使用的 Python 库是 Selen

  • Python3爬虫里关于识别微博宫格验证码的知识点详解

    本节我们来介绍一下新浪微博宫格验证码的识别,此验证码是一种新型交互式验证码,每个宫格之间会有一条指示连线,指示了我们应该的滑动轨迹,我们需要按照滑动轨迹依次从起始宫格一直滑动到终止宫格才可以完成验证,如图所示: 鼠标滑动后的轨迹会以黄色的连线来标识,如图所示: 我们可以访问新浪微博移动版登录页面就可以看到如上验证码,链接为:https://passport.weibo.cn/signin/login,当然也不是每次都会出现验证码,一般当频繁登录或者账号存在安全风险的时候会出现. 接下来我们就来试

  • Python3网络爬虫开发实战之极验滑动验证码的识别

    上节我们了解了图形验证码的识别,简单的图形验证码我们可以直接利用 Tesserocr 来识别,但是近几年又出现了一些新型验证码,如滑动验证码,比较有代表性的就是极验验证码,它需要拖动拼合滑块才可以完成验证,相对图形验证码来说识别难度上升了几个等级,本节来讲解下极验验证码的识别过程. 1. 本节目标 本节我们的目标是用程序来识别并通过极验验证码的验证,其步骤有分析识别思路.识别缺口位置.生成滑块拖动路径,最后模拟实现滑块拼合通过验证. 2. 准备工作 本次我们使用的 Python 库是 Selen

  • Python3爬虫关于识别点触点选验证码的实例讲解

    上一节我们实现了极验验证码的识别,但是除了极验其实还有另一种常见的且应用广泛的验证码,比较有代表性的就是点触验证码. 可能你对这个名字比较陌生,但是肯定见过类似的验证码,比如 12306,这就是一种典型的点触验证码,如图所示: 我们需要直接点击图中符合要求的图,如果所有答案均正确才会验证成功,如果有一个答案错误,验证就会失败,这种验证码就可以称之为点触验证码. 另外还有一个专门提供点触验证码服务的站点,叫做 TouClick,其官方网站为:https://www.touclick.com/,本节

  • laravel5.4生成验证码的实例讲解

    总结:本篇文章介绍使用gregwar/captcha实现验证码的具体操作步骤,以及可能遇到的问题和解决办法. 操作步骤: 1, 在laravel5.4项目根目录下找到 composer.json 这个文件, 添加 "gregwar/captcha": "1.*" 到composer.json这个文件中,如下图所示. 2. 然后打开命令行,找到项目的根目录,运行composer update, 可以看到这个扩展库已经下载好了, 3.接下来,就可以正常使用验证码了,先测

  • JS 60秒后重新发送验证码的实例讲解

    废话不多说,直接上代码 //settime($("#getPhoneCode"),60); function settime($obj, time) { if (time == 0) { $obj.attr("disabled", false); $obj.css("background", "#f38401").css("cursor", "pointer"); $obj.text(&

  • java接入创蓝253短信验证码的实例讲解

    说明 项目是springboot框架 1.短信配置文件 包含验证码发送路径.用户名.密码 chuanglan.requesturl= chuanglan.account= chuanglan.pswd= 配置文件 具体值 查看官网 位置查看截图 红框已经标红 2.读取配置文件类 3.发送数据request实体类 public class SmsVariableRequest { private String account; private String password; private St

  • php实现自动生成验证码的实例讲解

    现在验证码在表单中的应用越来越多了,但是如果用js来实现总觉得不太方便,因此使用php来实现下,在此记录下. 当然,我们也可以封装成一个函数,以后使用的时候也是很方便的,这里并未封装,感兴趣的小伙伴可以自己封装下. 具体实现代码: 新建一个cap_sz.php文件: <?php session_start(); //设置session,一定要在顶部 $width = 150; //设置图片宽为300像素 $height = 40; //设置图片高为40像素 $image = imagecreat

  • php生成图片验证码的实例讲解

    本文以实例演示5种验证码,并介绍生成验证码的函数.PHP生成验证码的原理:通过GD库,生成一张带验证码的图片,并将验证码保存在Session中. 1.HTML 5中验证码HTML代码如下: <div class="demo"> <h3>1.数字验证码</h3> <p>验证码:<input type="text" class="input" id="code_num" nam

  • Python爬虫模拟登陆哔哩哔哩(bilibili)并突破点选验证码功能

    写在前面   今天带给大家一个突破点选验证码的案例,利用爬虫模拟登陆哔哩哔哩,并且把一些采坑的地方给大家强调一下,避免大家想我一样(唉,菜鸡本菜)还是老规矩在文末会附上完整代码,需要的小伙伴自取就好了,能帮助到你的话别忘了点赞关注喔~   郑重声明:本人目前仅在CSDN这一个平台发布文章,其他小伙伴如果想转载 或者引用请注明引用来源,未经许可不得直接搬运,请尊重创作人的劳动成果,谢谢! 一.需求分析   模拟登陆哔哩哔哩   网站链接: https://passport.bilibili.com

随机推荐