极验验证码:需要手动拼合滑块来完成的验证,相对图形验证码识别难度上升了几个等级。下面用程序识别并通过极验验证码的验证,其中有分析识别思路、识别缺口位置、生成滑块拖动、模拟实现滑块拼合通过验证等步骤。需要用到Chrome 浏览器,并配置 ChromeDriver ,要用到的 Python 库是 Selenium。

1、 对极验验证码了解
  极验验证码官网:http://www.geetest.com/。一个专注提供验证安全的系统,主要验证方式是拖动滑块拼命图像。若图像完全拼合,则验证成功,即表单提交,否则需要重新验证。

现在极验验证码使用的企业很多,每天有超过几亿次的响应。极验验证码广泛用于直播视频、金融服务、电子商务、游戏娱乐、政府企业等各大类网站。

2、 极验验证码特点
  识别难度大。首先要点击按钮进行智能验证,如果验证不通过,则会弹出滑动窗口,拖动滑块拼合图像进行验证。之后三个加密参数会生成,通过表单提交到后台,后台还会进行一次验证。

极验验证码增加了机器学习的方法来识别手动轨迹。其官方网站的安全防护有下面几点说明:

  • 三角防护之防模拟:恶意程序模仿人类行为轨迹对验证码进行识别。利用机器学习和神经网络,构建线上线下的多重静态、动态防御模型,识别模拟轨迹,界定人机边界。

  • 三角防护之防伪造:恶意程序通过伪造设备浏览器环境对验证码进行识别。利用设备基因技术,深度分析浏览器的实际性能来辨识伪造信息,同时根据依靠事件不断更新黑名单来提高防依靠能力。

  • 三角防护之防暴力:恶意程序在短时间内进行密集的攻击,对验证码进行暴力识别。为了防暴力,极验验证码有多种形态,每种形态都用神经网络生成海量图库储备,每一张图片都是独一无二的,且图库不断更新,极大程度提高防暴力识别成本。

3、 识别思路
  对于极验验证码,直接模拟表单提交,加密参数构造较困难,需要分析其加密和校验逻辑,相对烦琐。所以直接采用模拟浏览器动作的方式来完成验证。使用 Python 的 Selenium 库模拟人的行为方式来完成验证,成本要相对去识别加密算法少很多。如图所示。

!极验验证码实例](https://img2018.cnblogs.com/blog/1501522/201905/1501522-20190520165616663-50859391.png)

先找一个带有极验证的网站,这里以博客园的登录为例进行验证。极验的官方登录网站是 https://account.geetest.com/login,也可以在其官网上做测试。在博客园的登录页面点击登录后会出现一个极验验证按钮。如图2-2所示。

极验验证按钮

该按钮是智能验证按钮。一般来说,如果是同一个会话,一段时间内第二次点击会直接通过验证。如果智能识别不通过,则会弹出滑动验证窗口,需要拖动滑块图像完成二步验证。验证成功后,验证按钮会提示验证成功。接下来就是提交表单。

经过上述分析,极验验证需要完成下面三步:
(1)模拟点击验证按钮。
(2)识别滑动缺口的位置。
(3)模拟手动滑块。

第(1)步操作相对简单,可使用 Selenium 模拟点击按钮。
第(2)步操作识别缺口的位置很关键,需要用到图像的相关处理方法。首先观察缺口的样子,如图所示。

图2-3 缺口示例

缺口的四周边缘有明显的断裂边缘,边缘与边缘周围有明显的区别。可用边缘检测算法来找出缺口的位置。对于极验验证码,可以利用和原图对比检测方式识别缺口的位置,通常在没有拖动滑块前,缺口没有呈现。

可以同时获取两张图片,设定一个对比阈值,然后遍历两张图片,找出相同位置像素 RGB 差距超过此阈值的像素点,此像素点的位置就是缺口的位置。

第(3)步中要注意的是,极验验证码增加了机器轨迹识别,匀速移动、随机速度移动等方法都不能通过验证,只有完全模拟人的移动轨迹才可以通过验证。人的移动轨迹一般是先加速后减速,要对这个过程模拟才能成功。

要包括这几个步骤。第一步,初始化,在这里我们先初始化 一些selenium的 配置及一些参数的配置。第二步,就是模拟点击了,这里主要是利用selenium模块模拟浏览器对网页进行操作。第三步,就该识别缺口的位置了。首先获取前后两张图片,得到其所在位置和宽高,然后获取整个网页的截图,图片裁切下来即可。最后一步,模拟拖动,经过多次试验,得出一个结论,那就是完全模拟加速减速的过程通过了验证。前段作匀加速,后段作匀减速运动,利用物理学的加速度公式即可完成验证。

位移移动

需要的基础知识

位移移动相当于匀变速直线运动,类似于小汽车从起点开始运行到终点的过程(首先为匀加速,然后再匀减速)。

其中a为加速度,且为恒量(即单位时间内的加速度是不变的),t为时间

教程一:博客园

误区一:

下面整个button区域对应着整个登录框,可以直接使用id里的标签进行定位,而不是第1个span标签

button = self.wait.until(EC.presence_of_element_located((By.ID,"submitBtn")))

误区二:注意关于图片的一些知识点

img1 = Image.open("E:/python27/pic/1.jpg")
img1.size
r, g, b = img1.split()打开图片:Image.open(fp, mode='r')
保存图片:Image.save(fp, format=None, **params):
展示图片:Image.show(title=None, command=None):
location = img.location
# location属性可以返回该图片对象(既这张图片)在浏览器中的位置,以字典的形式返回,{‘x’:30,‘y’:30} 这里我们图片的位置是(30,30)。坐标轴是以屏幕左上角为原点,x轴向右递增,y轴像下递增。(相对整个html的坐标)size = img.size
# 通过size获取属性大小,size属性同样返回一个字典,{‘height’:30,‘width’:30 } 即图片对象的高度,宽度。four_corner =(location['x'],location['y'],location['x']+size['width'],location['y']+size['height'])
# 通过location和size获取上下左右,注意是小写的x和ycaptcha = screenshot.crop((top, bottom, left, right))
# Image.crop() 从图像中提取出某个矩形大小的图像。它接收一个四元素的元组作为参数,各元素为(left, upper, right, lower),坐标系统的原点(0, 0)是左上角。# 因为上面截图,截取到的是整个页面,现在只把验证码图片取到image.size属性是一个列表,下标0是横坐标(宽,图片的最右边),下标1是纵坐标
image.size[0]
image.size[1]

完整代码

from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
from selenium import webdriver
# import PIL.Image as image
from PIL import Image
from io import BytesIO
import timeEMAIL =
PASSWORD =
BODER = 6
INIT_LEFT = 60class CrackGeetest():def __init__(self):self.url = 'http://www.sf-express.com/cn/sc/dynamic_function/waybill'self.browser = webdriver.Chrome('D:\\chromedriver.exe')self.wait = WebDriverWait(self.browser, 100)self.email = EMAILself.keyword = PASSWORDself.BORDER = 6def 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_geetest_button(self):"""点击按钮,弹出没有缺口的图片:return: 返回按钮对象"""button = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_radar_tip')))return buttondef __del__(self):self.browser.close()def get_position(self):"""获取验证码位置:return:验证码位置元组"""img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))time.sleep(2)# location属性可以返回该图片对象(既这张图片)在浏览器中的位置,以字典的形式返回,{‘x’:30,‘y’:30} 这里我们图片的位置是(30,30)。坐标轴是以屏幕左上角为原点,x轴向右递增,y轴像下递增。(相对整个html的坐标)location = img.location# size属性同样返回一个字典,{‘height’:30,‘width’:30 } 即图片对象的高度,宽度。size = img.size                 # 通过sizes属性获取大小top,bottom,left,right = location['y'],location['y']+size['height'],location['x'],location['x']+size['width']    # 通过location和size获取上下左右return (top,bottom,left,right)def get_screenshot(self):"""获取网页截图:return: 截图对象"""pic.png = self.browser.get_screenshot_as_png()screenshot = Image.open(BytesIO(pic.png))            # 转换为字节对象'''img1 = Image.open("E:/python27/pic/1.jpg")img1.sizer, g, b = img1.split()打开图片:Image.open(fp, mode='r')保存图片:Image.save(fp, format=None, **params):展示图片:Image.show(title=None, command=None):'''def get_geetest_image(self, name='captcha.jpg'):"""获取验证码图片:return: 图片对象"""top, bottom, left, right = self.get_position()                  # 定位到这个位置之后,再截图print('验证码位置',top, bottom, left, right)screenshot = self.get_screenshot()                              # 获取到截图# Image.crop() 从图像中提取出某个矩形大小的图像。它接收一个四元素的元组作为参数,各元素为(left, upper, right, lower),坐标系统的原点(0, 0)是左上角。captcha = screenshot.crop((top, bottom, left, right))           # 因为上面截图,截取到的是整个页面,现在只把验证码图片取到captcha.save(name)                                              # 把图片存储起来,name是传进来的变量return captchadef get_slider(self):"""获取滑块:return: 滑块对象"""slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))return sliderdef is_pixel_equal(self, img1, img2, x, y):"""判断两个像素是否相同:param image1: 图片1:param image2: 图片2:param x: 位置x:param y: 位置y:return: 像素是否相同"""# 取两个图片的像素点 (img.load()[x, y]获取某一点的像素值)pixel1 = img1.load()[x, y]      # 上面的 i 和 jpixel2 = img2.load()[x, y]threshold = 60                  # 控制误差if (abs(pixel1[0] - pixel2[0] < threshold) and abs(pixel1[1] - pixel2[1] < threshold)           # 0 1 2 是RGB的三种颜色and abs(pixel1[2] - pixel2[2] < threshold)):return Trueelse:                           # 有一个超过阈值,则认为2个像素点不一致return Falsedef get_gap(self, img1, img2):"""获取缺口偏移量:param img1: 不带缺口图片:param img2: 带缺口图片:return:"""left = 60                                   # 从图片的60处开始往右,这样就可以把被拖动滑块跳过去,因为被拖动滑块处像素也不一样# 相当于从60开始,一列列做对比for i in range(left, img1.size[0]):         # i 相当于横坐标      size属性是一个列表,下标0是横坐标(宽,图片的最右边),下标1是纵坐标for j in range(img1.size[1]):           # j 相当于纵坐标      从0开始if not self.is_pixel_equal(img1, img2, i, j):left = i                                            # 如果相同位置的像素不一致,则替换为ireturn leftreturn leftdef get_track(self, distance):"""根据偏移量获取移动轨迹:param distance: 偏移量:return: 移动轨迹"""# 移动轨迹track = []# 当前位移current = 0# 减速阈值mid = distance * 4 / 5# 计算间隔t = 0.2# 初速度v = 0while current < distance:                   # 所以 track是不会大于总长度的if current < mid:# 加速度为正2a = 2else:# 加速度为负3a = -3# 初速度v0v0 = v# 移动距离x = v0t + 1/2 * a * t^2,现做了加速运动move = v0 * t + 1 / 2 * a * t * t# 当前速度v = v0 + at  速度已经达到v,该速度作为下次的初速度v = v0 + a * t# 当前位移current += move# 加入轨迹track.append(round(move))                   # track 就是最终鼠标在 X 轴移动的轨迹return trackdef move_to_gap(self, slider, track):"""拖动滑块到缺口处:param slider: 滑块:param track: 轨迹:return:"""ActionChains(self.browser).click_and_hold(slider).perform()         # 利用动作链,获取slider,perform是for x in track:ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()       # xoffset横坐标,yoffset纵坐标。使得鼠标向前推进time.sleep(0.5)                                     # 推动到合适位置之后,暂停一会ActionChains(self.browser).release().perform()      # 抬起鼠标左键def login(self):"""登陆:return: None"""submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME,'login-btn')))submit.click()                      # 登陆按钮time.sleep(10)print('登陆成功')def crack(self):# 打开浏览器,输入用户名和密码self.open()# 点击按钮,弹出没有缺口的图片button = self.get_geetest_button()button.click()time.sleep(0.5)# 获取验证码图片image1 = self.get_geetest_image('captcha1.png')#点按呼出滑块slider = self.get_slider()slider.click()                              # 一般的验证码,只有点完slide按钮之后,才会出现缺口# 获取带缺口的验证码图片image2 = self.get_geetest_image('captcha2.png')# 获取缺口位置gap = self.get_gap(image1, image2)print('缺口位置', gap)# 减去缺口的位移(因为,滑块移动img1到img2的时候,允许有误差范围。在范围内,即使有几个像素差,也是可以接受的gap -= BODER# 获取移动轨迹track = self.get_track(gap)print('滑动轨迹',track)# 拖动滑块到缺口处。模拟人的行为习惯(先匀加速拖动后匀减速拖动),把需要拖动的总距离分成一段一段小的轨迹self.move_to_gap(slider, track)success = self.wait.until(EC.text_to_be_present_in_element((By.CLASS_NAME,'geetest_sucess_radar_tip_constant'),'验证成功')        # 证明极验成功)print(success)# 失败后重试if not success:self.crack()else:self.login()if __name__ == '__main__':print('开始验证')crack = CrackGeetest()crack.crack()print('验证成功')

还有可以识别极验验证码的api可以用

https://www.kancloud.cn/abcabc123/yiyunapi/1879968

Python爬虫 | 滑动验证码破解相关推荐

  1. python爬虫滑动验证码_爬虫:滑动验证解决方法及python实现

    爬虫时遇到滑动验证,基本思路是通过selenium操作浏览器,将滑动验证的原始图片和缺口图片进行对比,找出缺口位置,然后在利用selenium模拟拖动滑块,达到验证的目的.下面就以猪八戒网为例,进行操 ...

  2. python爬虫滑动验证码_python爬虫21 | 对于b站这样的滑动验证码,不好意思,照样自动识别...

    今天 要来说说滑动验证码了 大家应该都很熟悉 点击滑块然后移动到图片缺口进行验证 现在越来越多的网站使用这样的验证方式 为的是增加验证码识别的难度 那么 对于这种验证码 应该怎么破呢 接下来就是 打开 ...

  3. 网易云音乐python爬虫(Js破解)

    网易云音乐下载python爬虫(Js破解) 最近做了一个网易云音乐下载的python爬虫,功能就是输入歌曲的名字,程序自动下载网易音乐搜索界面的第一首歌(一般都是原唱排第一位).本文很适合小白学习,写 ...

  4. 作为一只Python爬虫:如何破解滑动验证码

    做爬虫总会遇到各种各样的反爬限制,反爬的第一道防线往往在登录就出现了,为了限制爬虫自动登录,各家使出了浑身解数,所谓道高一尺魔高一丈. 今天分享个如何简单处理滑动图片的验证码的案例. 类似这种拖动滑块 ...

  5. Python爬虫实战 | (16) 破解简书登录点触验证码

    在本篇博客中,我们将使用selenium模拟登录简书网站,破解其登陆时的滑动验证码. 我们需要使用验证码识别服务平台.超级鹰,来帮助我们破解点触验证码.下面的chaojiying.py文件用于调用超级 ...

  6. python爬虫拖动验证码_python爬虫学习:验证码之滑动验证码

    前面两个文章提到了普通图片的验证码识别,且尤其对于机器学习的识别方式精度相对会比较高.但是,现在开始流行滑动验证码,所以这里作者提及一点简单的滑动验证码识别技巧. 打开火狐浏览器,按下 F12 ,输入 ...

  7. 用Python 爬虫,如何破解谷歌验证码?

    ReCAPTCHA 介绍 可能大家还没听说过什么是 ReCAPTCHA,可能由于某些原因,这个验证码在国内出现不多,不过想必大家应该多多少少见过或用过.它长这个样子: 这时候,只要我们点击最前面的复选 ...

  8. python爬虫绕过验证码_爬虫怎样绕过验证码?

    叶湘伦:[文字篇]如何系统地自学 Python?​zhuanlan.zhihu.com 1,cookie登录利用cookie的特性:cookie会保持较长的时间,来避免用户频繁登录 cookie一般由 ...

  9. selenium自动化案例(二)滑动验证码破解

    文章目录 写在前面 大致思路 Python实现 几个小坑 写在前面 最近学习了滑动验证的一个破解思路,是利用OpenCV的图形匹配算法进行对比验证,从而推算出滑块移动的距离,在实际应用中比较常见,我主 ...

最新文章

  1. 在深度学习的路上,哪些框架或学习平台值得推荐?
  2. SAP MM 标准的采购订单预付款功能介绍
  3. 替换字符串指定位置字符 php,PHP substr_replace 替换字符串指定位置字符
  4. 5G NR 定时提前 Timing advance
  5. winddows 运行指令 (2)
  6. C# WPF MVVM开发框架Caliburn.Micro 名称Transformer⑩①
  7. 力扣算法001_两数之和
  8. 在html页面中使用模板继承,HTML静态模板的继承
  9. sequel pro mac_Mac手绘插画绘图软件推荐
  10. oracle11g 时间失效,关于oracle11g RAC 的CTSS与ntp时间同步的疑问
  11. 年月日_时间单位年月日是怎么得来的?
  12. vb.net 画多个矩形_电气原理图和接线图识图方法,电气接线图怎么画?
  13. 程序员的数学【线性代数高级】
  14. pdf文件过大怎么办?3种免费压缩PDF的方法
  15. 大数据告诉你,上海二手房到底难不难卖?
  16. excel转置怎么操作_Excel拆分文本,想怎么拆就怎么拆,简单易学,一看就会
  17. 愤怒的小鸟AR 版终于正式上架!场景超逼真
  18. Java下载excel模板
  19. 群控 云控营销神器代码研究
  20. 安全距离:8...8米!?

热门文章

  1. easyui-tree 修改图标
  2. 视频AI边缘计算技术在安全生产监管中的场景化应用
  3. USB High Speed Inter-Chip (HSIC) IP: What is it? And why should I use it?
  4. 详解经历的各个广告联盟平台
  5. OpenGL实验(二三代码整理)桌子
  6. android iphone treeview,Android之IphoneTreeView带组指示器的ExpandableListView效果
  7. 【深度学习】基于pytorch的FER2013人脸表情图像识别(ResNet/VGG/DenseNet)
  8. Angular4搭建在线可竞拍网站
  9. 燃料电池聚合物电解质膜高低温退化性能测试中的TEC半导体制冷温控解决方案
  10. 秋招笔试_拼词游戏_Java版本