破解b站极验验证码

 

 

这就是极验验证码,通过拖动滑块移动拼图来验证。我们观察到点击滑块时拼图才会出现,所以我们可以在点击滑块之前截取图像,点击滑块再截取一次图像,将前后两次图像做比较就可以找到图片改动的位置。获得位置后,我们需要模拟人类的操作将滑块移动到指定的位置。代码如下:

#识别b站极验验证码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from io import BytesIO
import io
from PIL import Image
import time
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver import ActionChains

EMAIL = "wdl1078390625@qq.com"
PASSWORD = "wdl-075483267123"

class BilibiliTest():
    def __init__(self):
        self.url = "https://passport.bilibili.com/login"
        self.browser = webdriver.Chrome()
        self.wait = WebDriverWait(self.browser,20)
        self.email = EMAIL
        self.password = PASSWORD
        self.browser.get(self.url)
        email = self.wait.until(EC.presence_of_element_located((By.ID, 'login-username')))
        password = self.wait.until(EC.presence_of_element_located((By.ID, 'login-passwd')))
        email.send_keys(self.email)
        password.send_keys(self.password)

        self.button = self.get_test_button()
        self.img1,self.img2 = self.get_test_image()
        #保存图片
        self.img1.save('b1.png')
        self.img2.save('b2.png')
        
    def get_test_button(self):
        button = self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.gt_slider_knob')))
        return button
    
    #获得截图中图片的位置
    def get_position(self):
        action = ActionChains(self.browser)
        action.move_to_element(self.button)
        self.button.click()
        img = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.gt_cut_fullbg.gt_show')))
        location = img.location
        size = img.size
        top = location['y']
        bottom = location['y'] + size['height']
        left = location['x']
        right = location['x'] + size['width']
        return (top,bottom,left,right)
    
    #获得图片    
    def get_test_image(self):
        top,bottom,left,right = self.get_position()
        time.sleep(1)
        screenshot = self.get_screenshot()
        #浏览器缩放,所以要乘1.25,读者根据自己的需求修改之
        img1 = screenshot.crop((left*1.25,top*1.25,right*1.25,bottom*1.25))
        time.sleep(1)
        ActionChains(self.browser).click_and_hold(self.button).perform()
        time.sleep(1)
        screenshot = self.get_screenshot()
        img2 = screenshot.crop((left*1.25,top*1.25,right*1.25,bottom*1.25))
        return (img1,img2)
    
    #对比像素点是否一致
    def is_pixel_equal(self,img1,img2,x,y):
        pixel1 = img1.load()[x,y]
        pixel2 = img2.load()[x,y]
        #副本图片中常有干扰的灰块,与原图像素不一致但差距小,用threshold变量排除干扰
        threshold = 80
        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_gap(self,img1,img2):
        left = 80
        for i in range(left,img1.size[0]):
            for j in range(img1.size[1]-30):
                if not self.is_pixel_equal(img1,img2,i,j):
                    left = i
                    return left
        return left
        
    
    #获取滑块移动轨迹
    def get_track(self, distance):

        # 移动轨迹
        track = []
        current = 0
        mid = (distance-30) * 5 / 9
        mid2 = (distance-30) * 7 / 9
        t = 0.2
        # 初速度
        v = 3
        #初始加速度为2
        a = 2
        #初始加速度增量
        aa = 0.3
          
        while current < distance-25:
            if current < mid:
                a += aa
            elif current < mid2:
                a += aaelse:
                if a < 0 :
                    a -= aa
                else:
                    a = -a + 1
            # 初速度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 += round(move)
            # 加入轨迹
            track.append(round(move))

        track.append(0)
        track.append(-3)
        track.append(-2)
        print("distance:"+str(distance)+"track:")
        print(track)
        return track
    #移动滑块
    def move_to_gap(self,button,tracks):
        ActionChains(self.browser).click_and_hold(button).perform()
        for x in tracks:
            ActionChains(self.browser).move_by_offset(xoffset=x,
                yoffset=0).perform()
        time.sleep(0.3)
        ActionChains(self.browser).release().perform()
    
    #截屏
    def get_screenshot(self):
        screenshot = self.browser.get_screenshot_as_png()
        screenshot = Image.open(BytesIO(screenshot))
        return screenshot
        
    def login(self):
        distance = self.get_gap(self.img1,self.img2)
        track = self.get_track(distance)
        self.move_to_gap(self.button,track)
        time.sleep(10)
        

def main(args):
    bilibili = BilibiliTest()
    bilibili.login()
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main(sys.argv))

 

posted @ 2018-11-16 21:09  东东欧尼酱  阅读(886)  评论(0编辑  收藏  举报