极验滑动验证码

风流意气都作罢 提交于 2019-11-30 19:54:51
import timefrom io import BytesIOfrom PIL import Imagefrom selenium import webdriverfrom selenium.webdriver import ActionChainsfrom selenium.webdriver.common.by import Byfrom selenium.webdriver.support.ui import WebDriverWaitfrom selenium.webdriver.support import expected_conditions as ECEMAIL = '小白kill'PASSWORD = ''BORDER = 6class CrackGeetest():    def __init__(self):        self.url = 'https://account.cnblogs.com/signin'        options = webdriver.ChromeOptions()        options.add_experimental_option('excludeSwitches',                                        ['enable-automation'])        self.browser = webdriver.Chrome(options=options)        self.wait = WebDriverWait(self.browser, 20)        self.email = EMAIL        self.password = PASSWORD    def open(self):        '''        输入账号密码        :return: None        '''        self.browser.get(self.url)        email = self.wait.until(EC.presence_of_element_located((By.ID,'LoginName')))        email.clear()        password = self.wait.until(EC.presence_of_element_located((By.ID,'Password')))        email.send_keys(self.email)        password.send_keys(self.password)    def login(self):        """        登录        :return: None        """        submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'submitBtn')))        submit.click()        time.sleep(10)        print('登录成功')    def get_position(self):        '''        获取验证码位置        :return: 验证码位置元组        '''        img = self.wait.until(EC.presence_of_element_located((By.CLASS_NAME,'geetest_canvas_img')))        time.sleep(2)        location = img.location        size = img.size        print(size['height'])        print(size['width'])        top,bottom,left,right = location['y'] ,location['y']+size['height'],location['x'],location['x']+size['width']        return (top,bottom,left,right)    def get_geetest_image(self,name='captcha.png'):        """        获取验证码图片        :return: 图片对象        """        top, bottom, left, right = self.get_position()        print('验证码位置', top, bottom, left, right)        screenshot = self.get_screenshot()        captcha = screenshot.crop((left, top, right, bottom))        captcha.save(name)        return captcha    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,'geetest_slider_button')))        print(1)        return slider    def get_gap(self, image1, image2):        """        获取缺口偏移量        :param image1: 不带缺口图片        :param image2: 带缺口图片        :return:        """        left = 60        for i in range(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        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))        print(current)        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 delete_style(self):        '''        执行js脚本,获取无滑块图        :return:        '''        js = 'document.querySelectorAll("canvas")[2].style=""'        self.browser.execute_script(js)    def crack(self):        # 输入用户名密码        self.open()        # 点击登录按钮        self.login()        #获取滑块对象        slider = self.get_slider()        # 获取带缺口的验证码图片        image2 = self.get_geetest_image('captcha2.png')        # 获取验证码图片                js = 'document.querySelectorAll("canvas")[2].style=""'        self.browser.execute_script(js)        image1 = self.get_geetest_image('captcha1.png')        # 获取缺口位置        gap = self.get_gap(image1, image2)        print('缺口位置', gap)        # 减去缺口位移        gap -= BORDER        # 获取移动轨迹        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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!