贴吧旋转验证码---python破解代码

Posted 写BUG专家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了贴吧旋转验证码---python破解代码相关的知识,希望对你有一定的参考价值。


可识别百度贴吧旋转验证码,本人测试识别率为85%
github链接在文字尾部

以下是识别代码

r'''
百度贴吧验证码图片


'''


import tensorflow as tf
import keras.backend as K

import cv2
import numpy as np
import os
from PIL import Image


class my_ocr():
    def __init__(self):
        # physical_devices = tf.config.list_physical_devices('GPU')
        # tf.config.experimental.set_memory_growth(physical_devices[0], True)
        self.model = tf.keras.models.load_model(os.path.abspath("旋转验证码.hdf5"), custom_objects='angle_error':self.angle_error)

    def angle_difference(self,x, y):
        return 180 - abs(abs(x - y) - 180)

    #
    def angle_error(self,y_true, y_pred):
        diff = self.angle_difference(K.argmax(y_true), K.argmax(y_pred))
        return K.mean(K.cast(K.abs(diff), K.floatx()))

    def round(self,img_path, times):
        ima = Image.open(img_path).convert("RGBA")
        size = ima.size
        # 要使用圆形,所以使用刚才处理好的正方形的图片
        r2 = min(size[0], size[1])
        if size[0] != size[1]:
            ima = ima.resize((r2, r2), Image.ANTIALIAS)
        # 最后生成圆的半径
        r3 = int(r2 / 2)
        imb = Image.new('RGBA', (r3 * 2, r3 * 2), (255, 255, 255, 0))
        pima = ima.load()  # 像素的访问对象
        pimb = imb.load()
        r = float(r2 / 2)  # 圆心横坐标

        for i in range(r2):
            for j in range(r2):
                lx = abs(i - r)  # 到圆心距离的横坐标
                ly = abs(j - r)  # 到圆心距离的纵坐标
                l = (pow(lx, 2) + pow(ly, 2)) ** 0.5  # 三角函数 半径
                if l < r3:
                    pimb[i - (r - r3), j - (r - r3)] = pima[i, j]


        imb.save(times)
        return


    def gray(self,img_path):
        img = Image.open(img_path)
        Img = img.convert('L')
        Img.save(img_path)
    #旋转角度预测
    def identification(self,img_path):
        '''

        :param img_path: 图片地址 例如:D/1.png
        :return:
        '''

        # self.round(img_path,img_path)  #将图片变圆
        self.gray(img_path)  #转为灰度图片
        img_init = cv2.imread(img_path)
        img_init = cv2.resize(img_init, (224, 224))  # 将图片大小调整到224*224用于模型推理
        img = np.asarray(img_init)
        outputs = self.model.predict(img.reshape(1, 224, 224, 3))
        # print(outputs)
        result_index = int(np.argmax(outputs))
        class_names = ['0', '1', '10', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '11', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '12', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '13', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '14', '140', '141', '142', '143', '144', '145', '146', '147', '148', '149', '15', '150', '151', '152', '153', '154', '155', '156', '157', '158', '159', '16', '160', '161', '162', '163', '164', '165', '166', '167', '168', '169', '17', '170', '171', '172', '173', '174', '175', '176', '177', '178', '179', '18', '180', '181', '182', '183', '184', '185', '186', '187', '188', '189', '19', '190', '191', '192', '193', '194', '195', '196', '197', '198', '199', '2', '20', '200', '201', '202', '203', '204', '205', '206', '207', '208', '209', '21', '210', '211', '212', '213', '214', '215', '216', '217', '218', '219', '22', '220', '221', '222', '223', '224', '225', '226', '227', '228', '229', '23', '230', '231', '232', '233', '234', '235', '236', '237', '238', '239', '24', '240', '241', '242', '243', '244', '245', '246', '247', '248', '249', '25', '250', '251', '252', '253', '254', '255', '256', '257', '258', '259', '26', '260', '261', '262', '263', '264', '265', '266', '267', '268', '269', '27', '270', '271', '272', '273', '274', '275', '276', '277', '278', '279', '28', '280', '281', '282', '283', '284', '285', '286', '287', '288', '289', '29', '290', '291', '292', '293', '294', '295', '296', '297', '298', '299', '3', '30', '300', '301', '302', '303', '304', '305', '306', '307', '308', '309', '31', '310', '311', '312', '313', '314', '315', '316', '317', '318', '319', '32', '320', '321', '322', '323', '324', '325', '326', '327', '328', '329', '33', '330', '331', '332', '333', '334', '335', '336', '337', '338', '339', '34', '340', '341', '342', '343', '344', '345', '346', '347', '348', '349', '35', '350', '351', '352', '353', '354', '355', '356', '357', '358', '359', '36', '37', '38', '39', '4', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '5', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '6', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '7', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '8', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '9', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99']

        result = class_names[result_index]  # 获得名称

        return result






以下是调用代码


from ocr_code import my_ocr

 with open('1.jpg','wb')as f:
    f.write(img)
 f.close()
#1.png及是需要识别的旋转验证码
 result = my_ocr.identification('./1.png')
 print(result)

输入示例:

输出示例(上面的图片无关):

以下是测试代码:

import cv2
from selenium.webdriver.common.by import By
import random
from selenium.webdriver import ActionChains

from selenium import webdriver
import time
from lxml import etree
import requests
from selenium.webdriver.chrome.options import Options

# import my_ocr
from my_ocr import my_ocr


class my_web():
    def __init__(self):
        option = Options()

        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        option.add_argument('--disable-blink-features=AutomationControlled')
        self.driver = webdriver.Chrome(chrome_options=option)

    def __ease_out_expo(self,sep):
        if sep == 1:
            return 1
        else:
            return 1 - pow(2, -10 * sep)


    def generate_tracks(self, distance):
        """
        根据滑动距离生成滑动轨迹
        :param distance: 需要滑动的距离
        :return: 滑动轨迹<type 'list'>: [[x,y,t], ...]
            x: 已滑动的横向距离
            y: 已滑动的纵向距离, 除起点外, 均为0
            t: 滑动过程消耗的时间, 单位: 毫秒
        """
        distance = int(distance)
        if not isinstance(distance, int) or distance < 0:
            raise ValueError(f"distance类型必须是大于等于0的整数: distance: distance, type: type(distance)")
        # 初始化轨迹列表
        slide_track = [
            # [random.randint(-50, -10), random.randint(-50, -10), 0],
            [0, 0, 0],
        ]
        # 共记录count次滑块位置信息
        count = 30 + int(distance / 2)
        # 初始化滑动时间
        t = random.randint(50, 100)
        # 记录上一次滑动的距离
        _x = 0
        _y = 0
        for i in range(count):
            # 已滑动的横向距离
            x = round(self.__ease_out_expo(i / count) * distance)
            # 滑动过程消耗的时间
            t += random.randint(10, 20)
            if x == _x:
                continue
            slide_track.append([x, _y, t])
            _x = x
        slide_track.append(slide_track[-1])
        return slide_track


    def main(self):
        self.driver.get(
            'https://wappass.baidu.com/static/captcha/tuxing.html?ak=2ef521ec36290baed33d66de9b16f625&backurl=http%3A%2F%2Ftieba.baidu.com%2F&timestamp=1655176222&signature=7166d8dcec4ed272e5d84314de53e574')  # 打开url网页 比如 driver.get("http://www.baidu.com")
        ocr = my_ocr()
        while True:
            # 打开网页1
            time.sleep(3)
            html = self.driver.page_source
            # print(html)
            html = etree.HTML(html)
            url = html.xpath('//*[@class="vcode-spin-img"]/@src')[0]
            response = requests.get(url).content
            with open('./1.png', 'wb')as f:
                f.write(response)

            result = ocr.identification('./1.png')
            displacement_distance = 212 / 360 * int(result)
            print('预测旋转角度为:',result,'滑动距离为:',displacement_distance)
            source = self.driver.find_element(By.XPATH, r'//*[@class="vcode-spin-button"]/p')
            action = ActionChains(self.driver, duration=10)
            action.click_and_hold(source).perform()
            a = 0
            for x in self.generate_tracks(displacement_distance):
                # time.sleep(random.uniform(0.1,0.2))
                # print(x)
                action.move_by_offset(xoffset=x[0]-a, yoffset=x[1])
                a = x[0]

            action.release(source).perform()
            # ActionChains(self.driver).drag_and_drop_by_offset(b, xoffset=displacement_distance, yoffset=0).perform()
            time.sleep(2)
            if '热门吧' in self.driver.page_source以上是关于贴吧旋转验证码---python破解代码的主要内容,如果未能解决你的问题,请参考以下文章

PHP实现验证码

图形解锁验证码破解(附Python代码)

图形解锁验证码破解(附Python代码)

百度旋转验证码及同类型旋转验证码的识别思路

python+Selenium之自动滑块破解滑块验证码

Python大佬手把手带你用爬虫破解——滑动验证码识别