python版 —— 验证码校验 打码兔平台的使用介绍

1. 背景

验证码(CAPTCHA)的全称是全自动区分计算机和人类的图灵测试(Completely Automated Public Turing Test to tell Computers and Humans Apart),是一种用于区分人与计算机自动程序的挑战应答系统测试。CAPTCHA可通过设置一些人类很容易执行而自动程序很难完成的任务来区分人类和自动程序。
CAPTCHA经常被用来阻止自动程序使用博客来影响搜索引擎排名、签署电子邮箱帐户发送垃圾邮件或参与网上投票等。
通常,CAPTCHA是一个轻微扭曲的字母数字字符图像文件,人通常可以很容易读取图像中的字符。而自动程序能够识别该内容包含一个图像,但不知道是什么图像。考虑到弱视群体,一些CAPTCHA使用音频文件。在这样一个系统中,人可以听到一个字母或短句并打出他所听到的,从而证明他不是自动程序。

  • 一般来说,自动化处理验证码有两种方式:

    • 光学字符识别(Optical Character Recognition, OCR),从图像中抽取文本。主要的库有pytesser,tesseract。一般来说,对于复杂的验证码图像,需要先修改验证码图像,去除其中的背景噪音,只保留文本部分,再送入库中进行解析。而且识别率不是很高,想提高识别率,需要通过长时间机器学习的训练,代价较大。而且对于极其复杂的验证码,OCR甚至无法使用。
    • 使用验证码处理服务(借助于专业的打码平台)。付费调用他们提供的API。当把验证码图片传给他们的API时,会有人进行人工查看,并在HTTP响应中给出解析后的文本内容。一般来说,整个解析过程在10s(打码兔平台),最长60s,而且价位不高,1元 = 50~100个验证码(根据验证码类型进行收费)。如果验证码不多,为了提高识别效率和简化操作,就可以选择这种方式。

2. 环境

  • python 3.6.1
  • 系统:win7
  • IDE:pycharm
  • 安装过chrome浏览器
  • 配置好chromedriver
  • selenium 3.7.0

3. 打码兔平台的使用流程

3.1. 原理

  • 将验证码图片,打码平台账号,密码等按照指定格式调用API(访问URL),得到返回的结果。
  • 打码兔平台地址:http://www.dama2.com/
  • 打码兔平台开发者文档:http://wiki.dama2.com/index.php

3.2. 流程

  • 第一步:注册一个开发者帐号

  • 第二步:生成使用验证码的软件的ID和key
    登录开发者账号,进入 我的软件,点击创建软件,填好资料提交就会生成一个软件key的。

    备注:

    1. 把你的软件key填进相应的代码参数里面,然后把软件key发给打码兔的在线客服,他会帮你解除限制,你就可以用账号test,密码test测试了。
    2. 如图所示,这就是软件ID,软件名称,软件KEY,都是程序会用到的参数。
    3. 当别人使用你的软件ID和软件Key进行验证码消费时,作为软件的开发者是能拿到分成的。这也是抢票软件的赚钱的方式之一。也就是说,开发者帐号用于软件开发,赚钱。
    4. 软件不需要公开。而且开发者帐号不能进行付费打码。
  • 第三步:注册一个普通用户的帐号,并进行充值,用这个帐号进行付费打码。
    也就是说,开发者帐号用于赚钱,普通用户帐号用于付费打码

4. 自定义方法

  • 原始文档请参考官网:http://wiki.dama2.com/index.php?n=ApiDoc.Http

# 对打码兔平台提供的代码进行了一些改动,更加适应本软件的需求import hashlib
import urllib.request
import urllib
import json
import base64
import requests# md5加密字符串
def md5str(str):m = hashlib.md5(str.encode(encoding="utf-8"))return m.hexdigest()# md5加密byte
def md5(byte):m = hashlib.md5(byte)return m.hexdigest()# 打码兔API类
class DamatuApi():# 关联的开发者帐号# 此帐号关联的验证码类型,默认是1~8位随机英文和数字组合ID = '51773'  # 开发者帐号 软件的AppIDKEY = 'fbfb9022a1499b0c6436f223f98b714e'  # 开发者帐号 软件的key,   我的软件 生成的Key# 打码平台hostHOST = 'http://api.dama2.com:7766/app/'def __init__(self, username, password, limitCount):self.username = usernameself.password = password# 限制每个实例请求验证码的次数,防止意外,导致请求验证码过多,消费不可控self.limitCount = limitCount# 用于统计验证码请求次数self.count = 0# 计算用户签名,按照一定的规则对 key和userName 进行加密def getSign(self, param=b''):return (md5(bytes(self.KEY, encoding="utf8") + bytes(self.username, encoding="utf8") + param))[:8]# 获得加密后的密钥 key , userName, passworddef getPwd(self):return md5str(self.KEY + md5str(md5str(self.username) + md5str(self.password)))# 向打码平台提交请求def post(self, urlPath, formData = {}):''':param urlPath: 用于构造url,向不同的地址请求不同的数据:param formData: 提交的数据:return:'''url = self.HOST + urlPathtry:response = requests.request(method='post',url=url,data=formData,timeout=60)print(f"text = {response.text}")# 余额,balance, text = {"ret":0,"balance":"9957","sign":"2428e5f9"}# 验证码,captcha, text = {"ret":0,"id":558899326,"result":"230876","sign":"8d55bdb1"}return response.textexcept Exception as e:print(f"postRequest error. exception = {e}, urlPath = {urlPath}, formData = {formData}")return {"ret": -1}# 查询余额 return 是正数为余额, 如果为负数 则为错误码def getBalance(self):data = {'appID': self.ID,'user': self.username,'pwd': self.getPwd(),'sign': self.getSign()}res = self.post('d2Balance', data)jres = json.loads(res)if jres['ret'] == 0:return (True, jres['balance'])else:return (False, jres['ret'])# 上传验证码图片def decode(self, filePath, type):''':param filePath:  验证码图片路径 如d:/1.jpg:param type: 验证码类型,查看http://wiki.dama2.com/index.php?n=ApiDoc.Pricedesc:return: 元组,result[0] = True为成功,False为错误码'''if self.count >= self.limitCount:print(f"decode: 请求验证码数量超过限制自定义数量。")return (False, False)# 拿到验证码图片的数据f = open(filePath, 'rb')fdata = f.read()filedata = base64.b64encode(fdata)f.close()data = {'appID': self.ID,'user': self.username,'pwd': self.getPwd(),'type': type,'fileDataBase64': filedata,'sign': self.getSign(fdata)}res = self.post('d2File', data)jres = json.loads(res)self.count += 1if jres['ret'] == 0:# 注意这个json里面有ret,id,result,cookie,根据自己的需要获取return (True, jres['result'])else:return (False, jres['ret'])# url地址打码,提供验证码链接def decodeUrl(self, url, type):''':param url: 验证码地址:param type: 验证码类型 http://wiki.dama2.com/index.php?n=ApiDoc.Pricedesc:return: 元组,result[0] = True为成功,False为错误码'''if self.count >= self.limitCount:print(f"decodeUrl: 请求验证码数量超过限制自定义数量。")return (False, False)data = {'appID': self.ID,'user': self.username,'pwd': self.getPwd(),'type': type,'url': urllib.parse.quote(url),'sign': self.getSign(url.encode(encoding="utf-8"))}res = self.post('d2Url', data)jres = json.loads(res)self.count += 1if jres['ret'] == 0:# 注意这个json里面有ret,id,result,cookie,根据自己的需要获取return (True, jres['result'])else:return (False, jres['ret'])# 报错,暂时先不关心。 参数id(string类型)由上传打码函数的结果获得 return 0为成功 其他见错误码def reportError(self, id):data = {'appID': self.ID,'user': self.username,'pwd': self.getPwd(),'id': id,'sign': self.getSign(id.encode(encoding="utf-8"))}res = self.post('d2ReportError', data)res = str(res, encoding="utf-8")jres = json.loads(res)return jres['ret']

5. 嵌入代码中使用

验证码截图,请参考文章:http://blog.csdn.net/zwq912318834/article/details/78605486

  • 第一步,确保余额充足
# 打码兔API类 实例化,参数是打码兔用户账号和密码. 最后一个是限制验证码的次数,防止出故障时,无限刷验证码,消费过大
# dmt=DamatuApi("test","test")
# 目前本软件验证码定位为: 1~8位数字英文混搭, 题分21分
dmt = DamatuApi("ancode", "ancode2017", 200)
# 先查看余额是否充足
# BalanceRes = (True, '9931')
balanceRes = dmt.getBalance()   # 查询余额
if balanceRes[0] == True and int(balanceRes[1]) > 0:# 余额充足, 可以放心爬取print(f"main: balanceRes = {balanceRes}")# 开始爬取数据#......
  • 第二步,验证码校验。

    • 检测验证码是否出现。
    • 对验证码进行截图。
    • 发送验证码图片进行解码。
    • 向网站提交验证码解析结果。
    • 检测验证码是否校验成功。
    • 注意:每一次页面的变动,都可能让之前获取的元素失焦,需要重新获取。
# 部分代码
# 通过Image处理图像,截取验证码图片
imgCaptcha.save('clawerImgs/captcha.png')# 将验证码送往打码兔进行解码
# codeRes = (True, 'FMAE')
# 56 代表验证码类型,1~8位数字英文组合
# 参考:http://wiki.dama2.com/index.php?n=ApiDoc.Pricedesc
damatuRes = DamatuInstance.decode('clawerImgs/captcha.png', 56)
while(damatuRes[0] == False):if damatuRes[1] == False:raise Exception(f"打码兔超出自定义最大限制数,终止软件. damatuRes = {damatuRes}")else:# 验证码请求失败,查询下余额,看是否充足balanceRes = DamatuInstance.getBalance()if balanceRes[0] == True and int(balanceRes[1]) > 0:damatuRes = DamatuInstance.decode('clawerImgs/captcha.png', 56)time.sleep(2)else:# 打码兔 余额不足, 抛出异常,终止软件raise Exception(f"打码兔余额不足,或者超出自定义最大限制数,终止软件. balanceRes = {balanceRes}")# 点击提交按钮
input = browser.find_element_by_xpath("//div[@class='input']/input[@id='J_CodeInput']")
input.clear()
input.send_keys(damatuRes[1])
print(f"发送验证码为: damatuRes = {damatuRes}")
time.sleep(3)
# 提交
submit = browser.find_element_by_xpath("//button[@id='J_submit']")
submit.click()
time.sleep(5)
################################################
# 处理完,提交完验证码之后,回归到主页面,继续抓取商品
browser.switch_to.default_content()
time.sleep(2)
browser.refresh()   # 处理完之后进行页面刷新
time.sleep(5)
# 然后重新检测验证码是否存在,如果还在就循环重复处理,如果不在,下面这个流程也不会继续
captchaHandler(browser, DamatuInstance)

python版 —— 验证码校验 打码兔平台的使用介绍相关推荐

  1. 重温经典:Python版飞机大战源码 神器 玩游戏就玩自己开发的

    目录 导语 正文 一.环境安装 二.我方飞机 三.敌方飞机 四.控制键盘移动 五.检测子弹碰撞 六.效果图 总结 免费源码领取处: 往期文章推荐-- Python从入门到实战-- 绘图Turtle系列 ...

  2. python版飞机大战源码和素材免费

    个人写的python飞机大战 初学python 里面有两个版本 一个是多敌机版 一个是单敌机版 点击打开链接

  3. python版飞机大战及码源

    飞机大战是之前学习python时根据网上的代码改编写成的,有完整的代码和素材. 文件结构: images文件:放置程序所需要的图片素材 sound文件:放置程序所需要的声音素材 bullet.py:有 ...

  4. python版植物大战僵尸源码_基于python的植物大战僵尸游戏设计与实现.docx

    湖南理工学院毕业设计(论文) PAGE PAGE 1 学 号 毕业设计(论文) 题目:基于python的植物大战僵尸游戏设计与实现 作 者 届 别 届 院 别 信息与通信工程学院 专 业 信息工程 指 ...

  5. python版植物大战僵尸源码_用Python写一个植物大战僵尸! 简直一模一样!

    引入需要的模块 import pygame import random 配置图片地址 IMAGE_PATH = 'imgs/' 设置页面宽高 scrrr_width = 800 scrrr_heigh ...

  6. 面向对象编程(Python版详解)

    [辰兮要努力]:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端.后台.数据 ...

  7. Thinkphp开发App网络授权验证系统源码

    正文: Thinkphp开发App网络授权验证系统源码,没有过多的介绍,大家自己去研究吧,有ZF接口,卡Mi管理,Ying用管理,Yong户管理等功能. 下载方式: lanzou.com/iAYMm0 ...

  8. 全新Thinkphp开发App网络授权验证系统源码

    正文: Thinkphp开发App网络授权验证系统源码,没有过多的介绍,大家自己去研究吧,有支付接口,卡卡密管理,应用用管理,用户管理等功能. 程序: wwuyh.lanzoub.com/iAEmy0 ...

  9. python手工打码_打码兔和超人打码python版

    1.[代码][Python]代码 # coding:utf-8 from ctypes import * import requests import json import random impor ...

最新文章

  1. gb2312 requests乱码_不要相信requests返回的text
  2. 必备面试题:系统CPU飙高和GC频繁,如何排查?
  3. eventbus使用_Android EventBus框架的使用介绍
  4. [转] linux-Centos7安装python3并与python2共存
  5. 3_10 MediaMode 中介者模式
  6. Python + wordcloud + jieba 十分钟学会用任意中文文本生成词云
  7. 机器学习:贝叶斯和优化方法_Facebook使用贝叶斯优化在机器学习模型中进行更好的实验
  8. Win11控制面板里面怎么找到系统安全?
  9. java如何实现不固定个数传参
  10. OpenShift 4 之AMQ Streams(3) - 用Kafka MirrorMaker在Kafka集群间复制数据
  11. 数据可视化必备的高逼格图表特效,学会只需要五分钟
  12. 右)侧固定宽度,右(左)侧宽度自适应 ---清除浮动
  13. win10下安装numpy
  14. 进共享服务器提示信号灯超时,移动硬盘提示说无法访问,信号灯超时,时间已到是为什么啊...
  15. Java方法——方法的重载
  16. 双赛道近四百万奖金,2021全国人工智能大赛来了
  17. WEB 9.jQuery
  18. python人像精细分割_基于UNet网络实现的人像分割 | 附数据集
  19. 微信域名防封浅谈之一
  20. wolframalpha最新版_WolframAlpha下载-WolframAlpha ios版下载 苹果版V1.7.4-PC6苹果网

热门文章

  1. 浏览器输入一个URL过程
  2. 新年签通用php,C#开发微信门户及应用微信现金红包的封装及使用
  3. 量化回测平台Backtrader实战-陆一潇-专题视频课程
  4. Roce\Infiniband
  5. spring注解注入详解
  6. 笨办法学Python3 习题16
  7. 微光增强的深Retinex分解——思路整理
  8. android 闪烁效果,Android 微光闪烁效果之更强Shimmer-android
  9. C++获取屏幕分辨率(屏幕窗口大小),屏幕显示比例(DPI)几种方法
  10. HTML网页部分怎么与上面隔开,HTML网页制作讲义.ppt