滑动极限验证码破解

1,打开浏览器,并输入查询内容

class CrackGeetest():

    def __init__(self, url, proxy, word, searchId, bowtonID):

        self.url = url
        self.word = word  #  搜索关键词
        self.proxy = proxy  # 加上代理IP
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--proxy-server=%s' % self.proxy)
        # self.browser = webdriver.Chrome(chrome_options=chrome_options, executable_path='D:\\chromedriver')
        self.browser = webdriver.Chrome(chrome_options=chrome_options)
        self.wait = WebDriverWait(self.browser, 80)
        self.browser.set_page_load_timeout(40)
        self.searchId = searchId # 搜索框的ID,用于定位
        self.bowtonID = bowtonID # 点击按钮的ID,用于定位
        self.threshold = 60  # 验证码图片对比中RGB的差值,可调
        self.left = 50  # 验证码图片的对比中的起始坐标,即拖动模块的右边线位置
        self.deviation = 7  # 误差值,这个值是多次测试得出的经验值
        self.page_count = []

    def open(self):
        """
        打开浏览器,并输入查询内容
        """
        self.browser.maximize_window()
        self.browser.get(self.url)
        if '无法访问此网站' in self.browser.page_source or '未连接到互联网' in self.browser.page_source or '该网页无法正常运作' in self.browser.page_source:  # 判断是否正常打开网页
            self.browser.quit()
        keyword = self.wait.until(EC.presence_of_element_located((By.ID, self.searchId)))
        bowton = self.wait.until(EC.presence_of_element_located((By.ID, self.bowtonID)))
        try:
            keyword.send_keys(self.word)  # 发送关键词
        except:
            keyword.send_keys(self.word)
        try:
            bowton.send_keys(Keys.ENTER) # 此处有坑!!!可能打开的窗口大小不同,导致网页上的元素重叠在一起,不能进行点击,因此直接进行Enter键进入
        except:
            bowton.send_keys(Keys.ENTER)

2,执行js,生成带缺口和不带缺口的验证码图片

    def get_image(self):
        """
        获取验证码图片
        :return: 验证码图片对象
        """
        times = random.uniform(3, 5)
        times = round(times, 2)
        time.sleep(times)
        bg_js = 'return document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png");'  # 带缺口验证码图片js
        fullbg_js = 'return document.getElementsByClassName("geetest_canvas_fullbg geetest_fade geetest_absolute")[0].toDataURL("image/png");'  # 完整验证码图片js
        #  执行 JS 代码并拿到图片 base64 数据
        bg_info = self.browser.execute_script(bg_js)  # 执行js文件得到带图片信息的图片数据
        bg_base64 = bg_info.split(',')[1]  # 拿到base64编码的图片信息
        bg_bytes = base64.b64decode(bg_base64)  # 转为bytes类型
        bg_image = Image.open(BytesIO(bg_bytes)) # image读取图片信息
        fullbg_info = self.browser.execute_script(fullbg_js)  # 执行js文件得到带图片信息的图片数据
        fullbg_base64 = fullbg_info.split(',')[1]  # 拿到base64编码的图片信息
        fullbg_bytes = base64.b64decode(fullbg_base64)  # 转为bytes类型
        fullbg_image = Image.open(BytesIO(fullbg_bytes)) # image读取图片信息
        return bg_image,fullbg_image

3,拿到滑动验证码需要移动的距离

    def get_distance(self,image1,image2):
        """
        拿到滑动验证码需要移动的距离
        :param image1: 没有缺口的图片对象
        :param image2: 带缺口的图片对象
        :return: 需要移动的距离
        """
        i = 0
        for i in range(self.left, image1.size[0]):
            for j in range(image1.size[1]):
                rgb1 = image1.load()[i, j]
                rgb2 = image2.load()[i, j]
                res1 = abs(rgb1[0] - rgb2[0])
                res2 = abs(rgb1[1] - rgb2[1])
                res3 = abs(rgb1[2] - rgb2[2])
                if not (res1 < self.threshold and res2 < self.threshold and res3 < self.threshold):
                    distance = i -self.deviation
                    return distance
        logging.debug('未识别出验证码中的不同位置,或图片定位出现异常')
        return i  # 如果没有识别出不同位置,则象征性的滑动,以刷新下一张验证码

4,生成滑动轨迹

这个轨迹是研究蛮久才出来的,因为极限验证会通过用户滑动轨迹的大数据,经过机器学习,来判定轨迹是机器滑动和人为滑动,之前网上先加速运动,再减速,什么区间震荡轨迹,刚开始还行,后面成功率就会越来越低,我的这个滑动轨迹至今还蛮稳定

    def get_track(self,distance):
        """
        :param distance:
        :return: 滑动轨迹
        """
        track = []
        current = 0
        mid = int(distance * round(random.uniform(0.6, 0.7), 2))
        jiansu = distance - mid  # 需要减速的距离
        # 计算间隔
        t = 0.2
        # 初速度
        v = 0
        while current < distance:
            if current < mid:
                # 设置加速度动态变化
                # Chrome 浏览器的加速度
                ap = random.uniform(3, 5)
                times = round(ap, 2)
                a = times
                # 初速度v0
                v0 = v
                v = v0 + a * t
                move = v0 * t + 1 / 2 * a * t * t + 0.5
                # 当前位移
                current += move
                # 加入轨迹
                track.append(round(move))
            else:
                a = -1 * (v * v) / (2 * jiansu)  #减速的速度
                v0 = v
                v = v0 + a * t
                if distance > 120:
                    move = v0 * t + 1 / 2 * a * t * t  - 1.5  # 1.5,1,0.5都是噪声,因为刚开始的减速距离挺大,为了尽量是最后的轨迹能够到1,就加了一些噪声
                elif distance <= 120 and distance >= 60:
                    move = v0 * t + 1 / 2 * a * t * t - 1
                else:
                    move = v0 * t + 1 / 2 * a * t * t - 0.5
                if move < 1:   # 减速运动如果后面move会越来越小,如果不让小于1的固定为1的话,有时候会进死循环
                    move = 1
                current += move
                track.append(round(move))
        return track

5,拖动滑块到缺口处

    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()

6,返回html

    def check_html(self, html):   # 检测一些html,如果成功,就可以返回html,不成功,就可以重试
        if 'geetest_success_radar_tip_content' in html:
            return True
        else:
            return False

结束语:

第一次写博客,学艺不精,往各位同仁不要见笑,希望能和各位多多交流,学无止境!!!上面只写了主要步骤,另外还有翻页,重试等没展示。在此申明,此博客只用于学习交流,不得进行非法用途!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值