最新-识别腾讯滑动验证码

腾讯防水墙滑动验证码破解

  • 使用OpenCV库
  • 成功率大概90%左右:在实际应用中,登录后可判断当前页面是否有登录成功才会出现的信息:比如用户名等。循环
  • 验证码地址:https://open.captcha.qq.com/online.html
  • 破解 腾讯滑动验证码
  • 腾讯防水墙
  • python + seleniuum + cv2
    来吧 结果展示:


    image

这里有一点很有意思
如果滑动过快或者滑动的又精确又快的话,有时会解锁不成功,所以这里使用了 模拟人滑动的方法:
加速度,多滑,划回来等 各种操作,各位也可以多试试。

    def get_track(distance):
        """
        模拟轨迹 假装是人在操作
        :param distance:
        :return:
        """
        # 初速度
        v = 0
        # 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
        t = 0.2
        # 位移/轨迹列表,列表内的一个元素代表0.2s的位移
        tracks = []
        # 当前的位移
        current = 0
        # 到达mid值开始减速
        mid = distance * 7 / 8
        distance += 10  # 先滑过一点,最后再反着滑动回来
        # a = random.randint(1,3)
        while current < distance:
            if current < mid:
                # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
                a = random.randint(2, 4)  # 加速运动
            else:
                a = -random.randint(3, 5)  # 减速运动
            # 初速度
            v0 = v
            # 0.2秒时间内的位移
            s = v0 * t + 0.5 * a * (t ** 2)
            # 当前的位置
            current += s
            # 添加到轨迹列表
            tracks.append(round(s))

            # 速度已经达到v,该速度作为下次的初速度
            v = v0 + a * t

        # 反着滑动到大概准确位置
        for i in range(4):
            tracks.append(-random.randint(2, 3))
        for i in range(4):
            tracks.append(-random.randint(1, 3))
        return tracks

代码在这里: github代码地址

show you the code!

#!/usr/bin/python
# -*- encoding: utf-8 -*-

'''
    企鹅滑动验证模拟登录
    python3 + seleniuum + cv2 + numpy
    后续优化可使用 pillow 将图片进一步灰度化处理
'''
import ssl

import requests

__doc__ = '小额通登录功能'

__author__ = 'silva'

import os
import cv2
import time
import random
import numpy as np
from PIL import Image
from urllib.request import urlretrieve

# selenium-part
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions

# third-part
from packages import config, util

save_path = os.path.join(config.APP_ROOT, 'data', 'xiaoetong.cookies')

headers = {
    # 'upgrade-insecure-requests': '1',
    # 'sec-fetch-site': 'none',
    # 'sec-fetch-mode': 'navigate',
    # 'sec-fetch-user': '?1',
    # 'dnt': '1',
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8',
    'accept-encoding': 'gzip, deflate, br',
    'if-modified-since': 'Thu, 26 Mar 2020 23:50:00 GMT',
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
    'cookie': 'pgv_pvi=2471064576; pgv_pvid=5782002132; RK=ONolY5oif/; ptcz=a47870ca7ab81fada934148d6f51e3b0f277d6392a83da1500c67160e342c143; fp3_id1=1100440A15DCB3607EBA9783B987E536B5B521433EED99ED52A9088B37DA960BFCE46BFDBAAF02D2619C6CC32454932FF3EE; pac_uid=0_5e72d24333325; XWINDEXGREY=0; pgv_info=ssid=s4198525417',
    'cache-control': 'max-age=0',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'
}

class Login(object):


    def __init__(self, **kwargs):
        # 初始变量信息
        self.__init_args__(**kwargs)

        # 运行主功能
        try:
            self.run()
        except Exception as e:
            util.traceback_info(e)
        # 退出浏览器
        self.after_quit()

    def __init_args__(self, **kwargs):
        self.count = "phone_number"
        self.pwd = "***"
        # 登录链接
        self.url = "https://admin.xiaoe-tech.com/login_page?xeuti=ituex#/acount"

    @staticmethod
    def show(name):
        cv2.imshow('Show', name)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

    @staticmethod
    def get_postion(chunk, canves):
        """
        判断缺口位置
        :param chunk: 缺口图片是原图
        :param canves:
        :return: 位置 x, y
        """
        otemp = chunk
        oblk = canves
        target = cv2.imread(otemp, 0)
        template = cv2.imread(oblk, 0)
        # w, h = target.shape[::-1]
        temp = 'temp.jpg'
        targ = 'targ.jpg'
        cv2.imwrite(temp, template)
        cv2.imwrite(targ, target)
        target = cv2.imread(targ)
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
        target = abs(255 - target)
        cv2.imwrite(targ, target)
        target = cv2.imread(targ)
        template = cv2.imread(temp)
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
        x, y = np.unravel_index(result.argmax(), result.shape)
        # print(result.argmax(), [x, y])
        return x, y
        # # 展示圈出来的区域
        # cv2.rectangle(template, (y, x), (y + w, x + h), (7, 249, 151), 2)
        # cv2.imwrite("yuantu.jpg", template)
        # show(template)

    @staticmethod
    def get_track(distance):
        """
        模拟轨迹 假装是人在操作
        :param distance:
        :return:
        """
        # 初速度
        v = 0
        # 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
        t = 0.2
        # 位移/轨迹列表,列表内的一个元素代表0.2s的位移
        tracks = []
        # 当前的位移
        current = 0
        # 到达mid值开始减速
        mid = distance * 7 / 8
        distance += 10  # 先滑过一点,最后再反着滑动回来
        # a = random.randint(1,3)
        while current < distance:
            if current < mid:
                # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
                a = random.randint(2, 4)  # 加速运动
            else:
                a = -random.randint(3, 5)  # 减速运动
            # 初速度
            v0 = v
            # 0.2秒时间内的位移
            s = v0 * t + 0.5 * a * (t ** 2)
            # 当前的位置
            current += s
            # 添加到轨迹列表
            tracks.append(round(s))
            # 速度已经达到v,该速度作为下次的初速度
            v = v0 + a * t
        # 反着滑动到大概准确位置
        for i in range(4):
            tracks.append(-random.randint(2, 3))
        for i in range(4):
            tracks.append(-random.randint(1, 3))
        return tracks

    def after_quit(self):
        """
        关闭浏览器
        :return:
        """
        self.driver.quit()
        # driver.close()关闭当前窗口
        # driver.quit()退出驱动关闭所有窗口

    def put_msg(self):
        try:
            # 获取手机号码输入框
            text_box = self.wait.until(
                expected_conditions.presence_of_element_located((By.XPATH, '//div[@class="inputBox"]/input')))
            text_pwd = self.wait.until(expected_conditions.presence_of_element_located(
                (By.XPATH, '//div[@class="passwordWrapper"]/div/input[@type="password"]')))
            # 获取发送验证按钮
            send_btn = self.wait.until(
                expected_conditions.presence_of_element_located((By.XPATH, '//div[@data-sensors="登录_登录页_点击登录"]')))
        except Exception as e:
            print(e)
            raise RuntimeError("获取 手机号码输入框 或者 发送验证按钮 失败,程序结束")
        text_box.send_keys(self.count)
        text_pwd.send_keys(self.pwd)
        try:
            action = ActionChains(self.driver)
            action.click(send_btn).perform()
        except Exception as e:
            print(util.traceback_info(e))
            return False

    def start_dirver(self):
        chrome_options = Options()
        chrome_options.add_argument('--headless')
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--disable-dev-shm-usage')
        self.driver = webdriver.Chrome(chrome_options=chrome_options)
        self.driver.maximize_window()
        self.wait = WebDriverWait(self.driver, 10)
        print('webdriver get: {0}'.format(self.url))
        self.driver.get(self.url)
        self.wait = WebDriverWait(self.driver, 10)

    def save_img(self, file_name, img_url):
        print('fetch img: {0}'.format(img_url))
        try:
            rs = requests.get(img_url, headers=headers, timeout=20)
        except Exception as e:
            print(e)
            time.sleep(0.5)
            rs = requests.get(img_url, headers=headers, timeout=20)
        content = rs.content
        save_path = os.path.join(config.APP_ROOT, 'data', file_name)
        with open(save_path, 'wb') as fp:
            fp.write(content)
        print('保存图片成功')

    def run(self):
        ssl._create_default_https_context = ssl._create_unverified_context
        requests.packages.urllib3.disable_warnings()
        self.start_dirver()
        # 填写用户信息并点击
        self.put_msg()
        time.sleep(3)
        # 判断是否需要进行验证
        if 'muti_index' in self.driver.current_url:
            return self.click_into_shop()
        else:
            self.driver.switch_to.frame(1)  # 切换到iframe模块
            time.sleep(3)
            # 等待图片加载完成
            slideBg = self.wait.until(
                expected_conditions.presence_of_element_located((By.XPATH, '//div/img[@id="slideBg"]')))
            # 判断图片是否加载完成
            bk_block = slideBg.get_attribute('src')  # 大图 url
            if not bk_block:
                print('等待图片加载中 ... ')
                time.sleep(2)
            # 获取背景图
            bk_block = self.driver.find_element_by_xpath('//img[@id="slideBg"]')  # 大图
            web_image_width = bk_block.size['width']
            bk_block_x = bk_block.location['x']

            # 获取缺口图
            slide_block = self.driver.find_element_by_xpath('//img[@id="slideBlock"]')  # 小滑块
            slide_block_x = slide_block.location['x']

            # 保存图片至本地
            slide_block_img = slide_block.get_attribute('src')
            bk_block_img = bk_block.get_attribute('src')

            # 保存图片
            img_bg_path = os.path.join(config.APP_ROOT, 'data', 'img_bg.png')
            img_slider_path = os.path.join(config.APP_ROOT, 'data', 'img_slider.png')
            self.save_img('img_slider.png', slide_block_img)
            self.save_img('img_bg.png', bk_block_img)

            # 获取web图与示例图的比例
            img_bkblock = Image.open(img_bg_path)
            real_width = img_bkblock.size[0]
            width_scale = float(real_width) / float(web_image_width)

            # 计算缺口位置
            position = self.get_postion(img_bg_path, img_slider_path)
            real_position = position[1] / width_scale
            # 减去滑块起始位置的距离
            real_position = real_position - (slide_block_x - bk_block_x)
            # 获取滑动距轨迹列表
            track_list = self.get_track(real_position)
            print('滑动轨迹:', int(real_position), track_list)
            # print('第一步,获取滑动按钮')
            button = self.wait.until(
                expected_conditions.presence_of_element_located((By.XPATH, '//div[@class="tc-drag-thumb"]')))
            ActionChains(self.driver).click_and_hold(on_element=button).perform()  # 点击鼠标左键,按住不放
            time.sleep(0.2)
            # print('第二步,拖动元素')
            for track in track_list:
                ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)
                time.sleep(0.002)
            # ActionChains(driver).move_by_offset(xoffset=-random.randint(0, 1), yoffset=0).perform()   # 微调,根据实际情况微调
            time.sleep(0.5)
            # print('第三步,释放鼠标')
            ActionChains(self.driver).release(on_element=button).perform()
            time.sleep(3)
            # 进入店铺激活usr_token 保存cookie
            return self.click_into_shop()


    def click_into_shop(self):
        '''进入店铺激活user_token'''
        try:
            shop = self.wait.until(expected_conditions.presence_of_element_located((By.XPATH, '//a[@class="shop-list-item shop-list-item__active"]')))
            ActionChains(self.driver).click(shop).perform()
        except Exception as e:
            print(util.traceback_info(e))
            return False
        print('等待3秒 ...')
        time.sleep(3)
        if '/index' in self.driver.current_url:
            return self.catch_cookies()
        return False

    def catch_cookies(self):
        '''
        成功缓存当前cookeis
        不成功 退出
        '''
        cookies = self.driver.get_cookies()
        _cookie_dict = {}
        for vo in cookies:
            _cookie_dict[vo['name']] = vo['value']
        # 保存cookie
        util.file(save_path, _cookie_dict)
        print('更新cookies成功')
        return True

if __name__ == '__main__':
    login = Login().run()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339