侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

python验证码识别教程之滑动验证码

Python  /  管理员 发布于 7年前   169

前言

上篇文章记录了2种分割验证码的方法,此外还有一种叫做”滴水算法”(Drop Fall Algorithm)的方法,但本人智商原因看这个算法看的云里雾里的,所以今天记录滑动验证码的处理吧。网上据说有大神已经破解了滑动验证码的算法,可以不使用selenium来破解,但本人能力不足还是使用笨方法吧。

基础原理很简单,首先点击验证码按钮后的图片是滑动后的完整结果,点击一下滑块后会出现拼图,对这2个分别截图后比较像素值来找出滑动距离,并结合selenium来实现拖拽效果。

至于selenium怎么安装就不说了,滑动验证码的一个难点就是要模拟人的拖拽行为,移动快了不行,慢了也不行。

这里以国家企业公示网站为例:

# -*- coding: utf-8 -*-import timeimport randomfrom io import BytesIOfrom PIL import Imagefrom selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECclass Slide(object): """滑动验证码破解""" def __init__(self, target): self.target = target # 要搜索的公司名称 self.driver = webdriver.Chrome() self.wait = WebDriverWait(self.driver, 10) def crop(self, left, top, right, bottom, pic_name): """截屏并裁剪""" ss = Image.open(BytesIO(self.driver.get_screenshot_as_png())) cp = ss.crop((left, top, right, bottom)) # 注意这里顺序 cp.save(pic_name) return cp def calc_move(self, pic1, pic2): """根据阈值计算移动距离""" pix1 = pic1.load() pix2 = pic2.load() threshold = 200 move = 0 # 因为滑块都从左向右滑动,而碎片本身宽度为60所以从60开始遍历 for i in range(60, pic1.size[0]):  flag = False  for j in range(pic1.size[1]):  r = abs(pix1[i, j][0] - pix2[i, j][0])  g = abs(pix1[i, j][1] - pix2[i, j][1])  b = abs(pix1[i, j][2] - pix2[i, j][2])  # if r > threshold and g > threshold and b > threshold:  # 方法1:分别判断rgb大于阈值  # flag = True  # break  if r + g + b > threshold:   # 方法2:判断rgb总和跟阈值比较,效果比1好 为什么呢??   flag = True   break  if flag:  move = i  break return move def path1(self, distance): """绘制移动路径方法1,构造一个等比数列""" q = 0.4 # 测试后发现0.4效果最佳 n = 10 # 最多移动几次 a1 = ((1 - q) * distance) / (1 - q**n) result = [] for o in range(1, n + 1):  an = a1 * q**(o - 1)  if an < 0.1: # 小于移动阈值的就不要了  break  t = random.uniform(0, 0.5) # 测试后0.5秒的间隔成功率最高  result.append([an, 0, t]) return result def path2(self, distance): """绘制移动路径方法2,模拟物理加速、减速运动,效果比1好""" result = [] current = 0 # 减速阈值 mid = distance * 4 / 5 # 计算间隔 t = 0.2 # 初速度 v = 0 while current < (distance - 10):  if current < mid:  # 加速度为正2  a = 2  else:  # 加速度为负3  a = -3  # 初速度v0  v0 = v  # 当前速度v = v0 + at  v = v0 + a * t  # 移动距离x = v0t + 1/2 * a * t^2  move = v0 * t + 0.5 * a * t * t  # 当前位移  current += move  # 加入轨迹  result.append([round(move), 0, random.uniform(0, 0.5)]) return result def run(self): self.driver.get("http://www.gsxt.gov.cn/index") input_box = self.driver.find_element_by_id('keyword') input_box.send_keys(self.target) search_btn = self.driver.find_element_by_id('btn_query') time.sleep(3) # 注意这里等一下再点,否则会出现卡死现象 search_btn.click() # 等待验证码弹出 bg_pic = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,         "gt_cut_fullbg"))) # html中坐标原点是左上角,右为x轴正方向,下为y轴正方向 # 输出的x为正就是此元素距离屏幕左侧距离 # 输出的y为正就是此元素距离屏幕上侧距离 # 所以我们需要截图的四个距离如下: top, bottom, left, right = (  bg_pic.location['y'], bg_pic.location['y'] + bg_pic.size['height'],  bg_pic.location['x'], bg_pic.location['x'] + bg_pic.size['width']) time.sleep(1) cp1 = self.crop(left, top, right, bottom, '1.png') # 获取滑块按钮并点击一下 slide = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,        "gt_slider_knob"))) slide.click() time.sleep(3) # 等3秒报错信息消失 TODO 这里应该可以改进 cp2 = self.crop(left, top, right, bottom, '2.png') move = self.calc_move(cp1, cp2) result = self.path1(move) # result = self.path2(move) # 拖动滑块 ActionChains(self.driver).click_and_hold(slide).perform() for x in result:  ActionChains(self.driver).move_by_offset(xoffset=x[0],yoffset=x[1]).perform()  # ActionChains(driver).move_to_element_with_offset(to_element=slide,xoffset=x[0],yoffset=x[1]).perform()  time.sleep(x[-1]) # 如果使用方法1则需要sleep time.sleep(0.5) ActionChains(self.driver).release(slide).perform() # 释放按钮 time.sleep(0.8) element = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, "gt_info_text"))) ans = element.text if u"通过" in ans:  # 这里也需要等一下才能获取到具体的链接  element = self.wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, "search_list_item")))  for o in self.driver.find_elements_by_xpath(u"//a[@target='_blank']"):  print(o.get_attribute("href"))  self.driver.quit() else:  print("识别失败")  self.driver.quit()if __name__ == '__main__': s = Slide('中国平安') s.run()

代码中注释很详细就不多说了,如果运行时候提示

selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home

则需要到 https://sites.google.com/a/chromium.org/chromedriver/home 下载驱动后解压到/usr/local/bin目录即可。
使用服务器运行时使用phantomjs替换chrome,另外失败的时候可以进行判断自动重试,有兴趣的小伙伴可以自己补充完善。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家的支持。


  • 上一条:
    python实现判断一个字符串是否是合法IP地址的示例
    下一条:
    python验证码识别教程之利用投影法、连通域法分割图片
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • PHP 8.4 Alpha 1现已发布!(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客