from selenium import webdriver # 用來驅動瀏覽器的 from selenium.webdriver import ActionChains # 破解滑動驗證碼的時候用的 能夠拖動圖片 import time from PIL import Image import random option = webdriver.ChromeOptions() option.add_argument('disable-infobars') driver = webdriver.Chrome(chrome_options=option) def get_snap(driver): # selenium自帶的截圖網頁全屏圖片 driver.save_screenshot('snap.png') img = driver.find_element_by_class_name('geetest_canvas_img') left = img.location['x'] upper = img.location['y'] right = left + img.size['width'] lower = upper + img.size['height'] # print(left, upper, right, lower) img_obj = Image.open('snap.png') # 對屏幕進行截取,獲取滑動驗證圖片 image = img_obj.crop((left, upper, right, lower)) return image def get_image1(driver): time.sleep(0.2) js_code = ''' var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="block"; console.log(x) ''' time.sleep(1) driver.execute_script(js_code) # 截取圖片 img_obj = get_snap(driver) return img_obj def get_image2(driver): time.sleep(0.2) js_code = ''' var x = document.getElementsByClassName('geetest_canvas_fullbg')[0].style.display="none"; console.log(x) ''' driver.execute_script(js_code) time.sleep(1) # 截取圖片 img_obj = get_snap(driver) return img_obj def get_distance(image1, image2): # 初始值 start = 60 # 滑塊色差 color_num = 60 for x in range(start, image1.size[0]): for y in range(image1.size[1]): rgb1 = image1.load()[x, y] rgb2 = image2.load()[x, y] r = abs(rgb1[0] - rgb2[0]) g = abs(rgb1[1] - rgb2[1]) b = abs(rgb1[2] - rgb2[2]) if not (r < color_num and g < color_num and b < color_num): return x - 7 def get_stacks(distance): distance += 20 ''' 勻加速\減速運行 v = v0 + a * t 位移: s = v * t + 0.5 * a * (t**2) ''' # 初速度 v0 = 0 # 加減速度列表 a_list = [3, 4, 5] # 時間 t = 0.2 # 初始位置 s = 0 # 向前滑動軌跡 forward_stacks = [] mid = distance * 3 / 5 while s < distance: if s < mid: a = a_list[random.randint(0, 2)] else: a = -a_list[random.randint(0, 2)] v = v0 stack = v * t + 0.5 * a * (t ** 2) # 每次拿到的位移 stack = round(stack) s += stack v0 = v + a * t forward_stacks.append(stack) back_stacks = [-1, -1, -2, -3, -2, -3 ,-2, -2, -3, -1] return {'forward_stacks': forward_stacks, 'back_stacks': back_stacks} def main(): try: driver.get('https://passport.cnblogs.com/user/signin') driver.implicitly_wait(5) # 1.輸入用戶名與密碼,點擊登陸 username = driver.find_element_by_id('input1') password = driver.find_element_by_id('input2') login_button = driver.find_element_by_id('signin') username.send_keys('_tank_') password.send_keys('*********') login_button.click() # 2.點擊滑動驗證按鈕,獲取圖片 geetest_button = driver.find_element_by_class_name('geetest_radar_tip') geetest_button.click() time.sleep(0.2) # 3.針對完整的圖片進行截取 image1 = get_image1(driver) # 4.針對有缺口的圖片進行截取 image2 = get_image2(driver) # 5.對比兩張圖片,獲取滑動距離 distance = get_distance(image1, image2) # 6.模擬人爲滑動軌跡 stacks = get_stacks(distance) # 7.根據滑動軌跡進行滑動 forward_stacks = stacks['forward_stacks'] back_stacks = stacks['back_stacks'] slider_button = driver.find_element_by_class_name('geetest_slider_button') time.sleep(0.2) ActionChains(driver).click_and_hold(slider_button).perform() time.sleep(0.2) for forward_stack in forward_stacks: ActionChains(driver).move_by_offset(xoffset=forward_stack, yoffset=0).perform() for back_stack in back_stacks: ActionChains(driver).move_by_offset(xoffset=back_stack, yoffset=0).perform() time.sleep(0.2) ActionChains(driver).move_by_offset(xoffset=5, yoffset=0).perform() ActionChains(driver).move_by_offset(xoffset=-5, yoffset=0).perform() ActionChains(driver).release().perform() time.sleep(50) finally: driver.close()