破解b站極驗驗證碼
阿新 • • 發佈:2018-11-16
這就是極驗驗證碼,通過拖動滑塊移動拼圖來驗證。我們觀察到點選滑塊時拼圖才會出現,所以我們可以在點選滑塊之前擷取影象,點選滑塊再擷取一次影象,將前後兩次影象做比較就可以找到圖片改動的位置。獲得位置後,我們需要模擬人類的操作將滑塊移動到指定的位置。程式碼如下:
#識別b站極驗驗證碼 from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from io importBytesIO import io from PIL import Image import time from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver import ActionChains EMAIL = "[email protected]" 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 #初始加速度增量的增量 aaa = 0.05 while current < distance-25: if current < mid: a += aa aa += aaa aaa += 0.02 elif current < mid2: a += aa aa += aaa else: if a < 0 : a -= aa aa += aaa aaa -=0.02 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))