zoukankan      html  css  js  c++  java
  • 极客验证码破解

    很多网站的登陆都有验证码一项,而极客的方案就是应用的非常普遍。更多的场景是反反爬虫的对抗中,极客验证码更是首选。

    图片来看一下

    点击后就出现上面的滑动图片的窗口。本文亲自尝试代码,来分享其中的坑。

    本文是使用selenium自动化测试工具来驱动代码完成验证,因此要有谷歌的driver和谷歌浏览器。以http://www.epicc.com.cn/idprovider/views/login.jsp为例子。

    首先

        def get_geetest_button(self):
            """
            获取初始验证按钮
            :return:
            """
            button = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'slide-tip')))
            return button
        
        def get_position(self):
            """
            获取验证码位置
            :return: 验证码位置元组
            """
    
            img=self.wait.until(EC.presence_of_element_located((By.CLASS_NAME ,'captcha-box-content')))
            time.sleep(2)
            location = img.location
            print(location)
            size = img.size
            top, bottom, left, right = location['y'], location['y'] + size['height'], location['x'], location['x'] + size[
                'width']
            print((top, bottom, left, right))
            # return (top, bottom, left, right)
            return (238, 400, 1103, 1473)
    
        def get_screenshot(self):
            """
            获取网页截图
            :return: 截图对象
            """
            name = int(time.time())
            screenshot = self.browser.get_screenshot_as_png()
            with open("screenshot"+ str(name) + ".png","wb")as f:
                f.write(screenshot)
    
            screenshot = Image.open(BytesIO(screenshot))
    
            return screenshot
        
        def get_slider(self):
            """
            获取滑块
            :return: 滑块对象
            """
            slider = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'slide-bar')))
            return slider
        
        def get_geetest_image(self, name='captcha.png'):
            """
            获取验证码图片
            :return: 图片对象
            """
            top, bottom, left, right = self.get_position()
            print('验证码位置', top, bottom, left, right)
            time.sleep(3)
            screenshot = self.get_screenshot()
            # crop函数带的参数为(起始点的横坐标,起始点的纵坐标,宽度,高度)
            captcha = screenshot.crop((left, top, right, bottom))
            captcha.save(name)
            return captcha
        
        def open(self):
            """
            打开网页输入用户名密码
            :return: None
            """
            self.browser.get(self.url)
            time.sleep(1)
            passLoginButton = self.browser.find_element_by_xpath("//ul[@class='login-tab-list']/li[2]")
            passLoginButton.click()
            email = self.wait.until(EC.presence_of_element_located((By.ID, 'entryId')))
            password = self.wait.until(EC.presence_of_element_located((By.ID, 'password')))
            email.send_keys(self.email)
            password.send_keys(self.password)
        
        def get_gap(self, image1, image2):
            """
            获取缺口偏移量
            :param image1: 不带缺口图片
            :param image2: 带缺口图片
            :return:
            """
    
            for i in range(INIT_LEFT, image1.size[0]):
                for j in range(image1.size[1]):
                    if not self.is_pixel_equal(image1, image2, i, j):
                        left = i
                        return left
    
        def is_pixel_equal(self, image1, image2, x, y):
            """
            判断两个像素是否相同
            :param image1: 图片1
            :param image2: 图片2
            :param x: 位置x
            :param y: 位置y
            :return: 像素是否相同
            """
            # 取两个图片的像素点
            pixel1 = image1.load()[x, y]
            pixel2 = image2.load()[x, y]
            threshold = 60
            if abs(pixel1[0] - pixel2[0]) < threshold and abs(pixel1[1] - pixel2[1]) < threshold and abs(
                    pixel1[2] - pixel2[2]) < threshold:
                return True
            else:
                return False
        
        def get_track(self, distance):
            """
            根据偏移量获取移动轨迹
            :param distance: 偏移量
            :return: 移动轨迹
            """
            # 移动轨迹
            track = []
            # 当前位移
            current = 0
            # 减速阈值
            mid = distance * 4 / 5
            # 计算间隔
            t = 0.2
            # 初速度
            v = 0
            
            while current < distance:
                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 + 1 / 2 * a * t * t
                # 当前位移
                current += move
                # 加入轨迹
                track.append(round(move))
            return track
        
        def move_to_gap(self, slider, track):
            """
            拖动滑块到缺口处
            :param slider: 滑块
            :param track: 轨迹
            :return:
            """
            ActionChains(self.browser).click_and_hold(slider).perform()
            for x in track:
                ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
            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, 'epiccLogin')))
            submit.click()
            time.sleep(10)
            print('登录成功')
        
        def crack(self):
            # 输入用户名密码
            self.open()
            # 点击验证按钮
            button = self.get_geetest_button()
            ActionChains(self.browser).move_to_element(button).perform()
            # button.click()
            time.sleep(5)
    
            # 获取验证码图片
            image1 = self.get_geetest_image('captcha1.png')
    
            # 点按呼出缺口
            print("点按呼出缺口")
            slider = self.get_slider()
            slider.click()
            # 获取带缺口的验证码图片
            image2 = self.get_geetest_image('captcha2.png')
            # 获取缺口位置
            gap = self.get_gap(image1, image2)
            print('缺口位置', gap)
            # 减去缺口位移 BORDER指的是待拼合的滑块距离验证码图片左边的距离(经过验证大多数网站滑块验证码这个值是是固定的)
            gap -= BORDER  #滑块要滑动的距离
            print("需要滑动的距离:{}".format(gap))
            gap = gap * 0.8
            # 获取移动轨迹
            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_success_radar_tip_content'), '验证成功'))
            print(success)
            
            # 失败后重试
            if not success:
                self.crack()
            else:
                self.login()
    
    
    if __name__ == '__main__':
        crack = CrackGeetest()
        crack.crack()
  • 相关阅读:
    最近相对闲点,写个笔记2
    最近相对闲点,写个笔记
    ORACLE 调优
    静态工厂方法与构造函数 创建类 区别
    组合与继承 区别
    Java异常
    abstract class 和 interface 区别
    java中的io系统详解
    Tomcat Apache 区别
    Vmware 下的网络模式配置
  • 原文地址:https://www.cnblogs.com/hd-zg/p/9010919.html
Copyright © 2011-2022 走看看