破解极验滑动验证
博客园登录url:
https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F
代码逻辑:
1、输入用户名与密码,并点击登录
2、弹出滑动验证,获取有缺口与完整的图片
3、通过像素点进行比对,获取滑动位移距离
4、模拟人的行为轨迹
5、开始滑动
1 from selenium import webdriver # 用来驱动浏览器的 2 from selenium.webdriver import ActionChains # 破解滑动验证码的时候用的 可以拖动图片 3 import time 4 from PIL import Image # pip3 install pillow 5 import random 6 7 # 截图图片函数 8 def cut_image(driver): 9 # 获取整个页面图片,图片名字为'snap.png' 10 driver.save_screenshot('snap.png') 11 12 # 获取滑动小画图 13 image = driver.find_element_by_class_name('geetest_canvas_img') 14 print(image.location) 15 print(image.size) 16 17 # 获取小图片的左上右下的位置 18 left = image.location['x'] 19 top = image.location['y'] 20 right = left + image.size['width'] 21 buttom = top + image.size['height'] 22 print(left, top, right, buttom) 23 24 # 调用open方法打开全屏图片并赋值给image_obj对象 25 image_obj = Image.open('snap.png') 26 27 # 通过image_obj对象对小图片进行截取 28 # box: The crop rectangle, as a (left, upper, right, lower)-tuple. 29 img = image_obj.crop((left, top, right, buttom)) 30 # 打开截取后的小图片 31 # img.show() 32 return img 33 34 # 获取完整图片 35 def get_image1(driver): 36 time.sleep(2) 37 38 # 修改document文档树,把完整图片的display属性修改为block 39 js_code = ''' 40 var x = document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display = "block"; 41 ''' 42 43 # 执行js代码 44 driver.execute_script(js_code) 45 46 # 截取图片 47 image = cut_image(driver) 48 49 return image 50 51 # 获取有缺口图片 52 def get_image2(driver): 53 time.sleep(2) 54 55 # 修改document文档树,把完整图片的display属性修改为block 56 js_code = ''' 57 var x = document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display = "none"; 58 ''' 59 60 # 执行js代码 61 driver.execute_script(js_code) 62 63 # 截取图片 64 image = cut_image(driver) 65 66 return image 67 68 # 获取滑块滑动距离 69 def get_distance(image1, image2): 70 # 小滑块右侧位置 71 start = 60 72 73 # 像素差 74 num = 60 75 print(image1.size) 76 for x in range(start, image1.size[0]): 77 for y in range(image1.size[1]): 78 79 # 获取image1完整图片每一个坐标的像素点 80 rgb1 = image1.load()[x, y] 81 82 # 获取image2缺口图片每一个坐标的像素点 83 rgb2 = image2.load()[x, y] 84 # (60, 86, 40) (60, 86, 40) rgb 85 print(rgb1, rgb2) 86 87 # abs获取绝对值, 像素点比较的值 88 r = abs(rgb1[0] - rgb2[0]) 89 g = abs(rgb1[1] - rgb2[1]) 90 b = abs(rgb1[2] - rgb2[2]) 91 92 # 如果条件成立,则找到缺口位置 93 if not (r < num and g < num and b < num): 94 # 有误差 - 7像素 95 return x - 7 96 97 # 模拟人的滑动轨迹 98 def get_strck_move(distance): 99 distance += 20 100 101 ''' 102 滑动行为轨迹 103 加速公式: 104 v = v0 + a * t 105 106 路程公式: 107 s = v0 * t + 0.5 * a * (t ** 2) 108 ''' 109 110 # 初速度 111 v0 = 0 112 113 # 时间 114 t = 0.2 115 116 # 位置 117 s = 0 118 119 # 滑动轨迹列表 向前滑动列表 120 move_list = [] 121 122 # 中间值,作为加减速度的位置 123 mid = distance / 5 * 3 124 125 # 加减速度列表 126 v_list = [1, 2, 3, 4] 127 128 # 循环位移 129 while s < distance: 130 if s < mid: 131 # 随机获取一个加速度 132 a = v_list[random.randint(0, len(v_list) - 1)] 133 134 else: 135 # 随机获取一个减速度 136 a = -v_list[random.randint(0, len(v_list) - 1)] 137 138 ''' 139 匀加速\减速运行 140 v = v0 + a * t 141 142 位移: 143 s = v * t + 0.5 * a * (t**2) 144 ''' 145 # 获取初始速度 146 v = v0 147 148 # 路程公式: 149 s1 = v * t + 0.5 * a * (t ** 2) 150 s1 = round(s1) # 取整 151 152 # 加速公式: 153 # v = v0 + a * t 154 m_v = v + a * t 155 156 # 把当前加/减速度赋值给初始速度,以便下一次计算 157 v0 = m_v 158 159 # 把位移添加到滑动列表中 160 move_list.append(s1) 161 162 # 修改滑动初始距离 163 s += s1 164 165 # 后退列表, 自定义后退滑动轨迹,必须是负值 166 back_list = [-1, -1, -2, -3, -2, -1, -1, -2, -3, -2, -1, -1] 167 168 return {'move_list': move_list, 'back_list': back_list} 169 170 def main(): 171 driver = webdriver.Chrome(r'D:\BaiduNetdiskDownload\chromedriver_win32\chromedriver.exe') 172 driver.implicitly_wait(10) 173 try: 174 driver.get('https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F') 175 176 # 1、输入用户名与密码,并点击登录 177 user_input = driver.find_element_by_id('LoginName') 178 user_input.send_keys('_tank_') 179 time.sleep(0.2) 180 181 pwd_input = driver.find_element_by_id('Password') 182 pwd_input.send_keys('k46709394.') 183 time.sleep(2) 184 185 login_submit = driver.find_element_by_id('submitBtn') 186 login_submit.click() 187 188 # 2、获取完整的图片 189 image1 = get_image1(driver) 190 191 # 3、获取有缺口图片 192 image2 = get_image2(driver) 193 194 # 4、比对两张图片,获取滑动距离 195 distance = get_distance(image1, image2) 196 print(distance) 197 198 # 5、模拟人的滑动轨迹 199 move_dict = get_strck_move(distance) 200 # 获取前进滑动轨迹 201 move_list = move_dict['move_list'] 202 # 获取后退滑动轨迹 203 back_list = move_dict['back_list'] 204 205 # 6、开始滑动 206 move_tag = driver.find_element_by_class_name('geetest_slider_button') 207 # 点击摁住滑动按钮 208 ActionChains(driver).click_and_hold(move_tag).perform() 209 210 # 向前滑动 211 for move in move_list: 212 ActionChains(driver).move_by_offset(xoffset=move, yoffset=0).perform() 213 time.sleep(0.1) 214 215 time.sleep(0.1) 216 217 # 向后滑动 218 for back in back_list: 219 ActionChains(driver).move_by_offset(xoffset=back, yoffset=0).perform() 220 time.sleep(0.1) 221 222 # 制作微妙晃动 223 ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform() 224 ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform() 225 226 time.sleep(0.1) 227 228 # 释放滑动按钮 229 ActionChains(driver).release().perform() 230 231 time.sleep(100) 232 233 finally: 234 driver.close() 235 236 if __name__ == '__main__': 237 main()from selenium import webdriver # 用来驱动浏览器的 238 from selenium.webdriver import ActionChains # 破解滑动验证码的时候用的 可以拖动图片 239 import time 240 from PIL import Image # pip3 install pillow 241 import random 242 243 # 截图图片函数 244 def cut_image(driver): 245 # 获取整个页面图片,图片名字为'snap.png' 246 driver.save_screenshot('snap.png') 247 248 # 获取滑动小画图 249 image = driver.find_element_by_class_name('geetest_canvas_img') 250 print(image.location) 251 print(image.size) 252 253 # 获取小图片的左上右下的位置 254 left = image.location['x'] 255 top = image.location['y'] 256 right = left + image.size['width'] 257 buttom = top + image.size['height'] 258 print(left, top, right, buttom) 259 260 # 调用open方法打开全屏图片并赋值给image_obj对象 261 image_obj = Image.open('snap.png') 262 263 # 通过image_obj对象对小图片进行截取 264 # box: The crop rectangle, as a (left, upper, right, lower)-tuple. 265 img = image_obj.crop((left, top, right, buttom)) 266 # 打开截取后的小图片 267 # img.show() 268 return img 269 270 # 获取完整图片 271 def get_image1(driver): 272 time.sleep(2) 273 274 # 修改document文档树,把完整图片的display属性修改为block 275 js_code = ''' 276 var x = document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display = "block"; 277 ''' 278 279 # 执行js代码 280 driver.execute_script(js_code) 281 282 # 截取图片 283 image = cut_image(driver) 284 285 return image 286 287 # 获取有缺口图片 288 def get_image2(driver): 289 time.sleep(2) 290 291 # 修改document文档树,把完整图片的display属性修改为block 292 js_code = ''' 293 var x = document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display = "none"; 294 ''' 295 296 # 执行js代码 297 driver.execute_script(js_code) 298 299 # 截取图片 300 image = cut_image(driver) 301 302 return image 303 304 # 获取滑块滑动距离 305 def get_distance(image1, image2): 306 # 小滑块右侧位置 307 start = 60 308 309 # 像素差 310 num = 60 311 print(image1.size) 312 for x in range(start, image1.size[0]): 313 for y in range(image1.size[1]): 314 315 # 获取image1完整图片每一个坐标的像素点 316 rgb1 = image1.load()[x, y] 317 318 # 获取image2缺口图片每一个坐标的像素点 319 rgb2 = image2.load()[x, y] 320 # (60, 86, 40) (60, 86, 40) rgb 321 print(rgb1, rgb2) 322 323 # abs获取绝对值, 像素点比较的值 324 r = abs(rgb1[0] - rgb2[0]) 325 g = abs(rgb1[1] - rgb2[1]) 326 b = abs(rgb1[2] - rgb2[2]) 327 328 # 如果条件成立,则找到缺口位置 329 if not (r < num and g < num and b < num): 330 # 有误差 - 7像素 331 return x - 7 332 333 # 模拟人的滑动轨迹 334 def get_strck_move(distance): 335 distance += 20 336 337 ''' 338 滑动行为轨迹 339 加速公式: 340 v = v0 + a * t 341 342 路程公式: 343 s = v0 * t + 0.5 * a * (t ** 2) 344 ''' 345 346 # 初速度 347 v0 = 0 348 349 # 时间 350 t = 0.2 351 352 # 位置 353 s = 0 354 355 # 滑动轨迹列表 向前滑动列表 356 move_list = [] 357 358 # 中间值,作为加减速度的位置 359 mid = distance / 5 * 3 360 361 # 加减速度列表 362 v_list = [1, 2, 3, 4] 363 364 # 循环位移 365 while s < distance: 366 if s < mid: 367 # 随机获取一个加速度 368 a = v_list[random.randint(0, len(v_list) - 1)] 369 370 else: 371 # 随机获取一个减速度 372 a = -v_list[random.randint(0, len(v_list) - 1)] 373 374 ''' 375 匀加速\减速运行 376 v = v0 + a * t 377 378 位移: 379 s = v * t + 0.5 * a * (t**2) 380 ''' 381 # 获取初始速度 382 v = v0 383 384 # 路程公式: 385 s1 = v * t + 0.5 * a * (t ** 2) 386 s1 = round(s1) # 取整 387 388 # 加速公式: 389 # v = v0 + a * t 390 m_v = v + a * t 391 392 # 把当前加/减速度赋值给初始速度,以便下一次计算 393 v0 = m_v 394 395 # 把位移添加到滑动列表中 396 move_list.append(s1) 397 398 # 修改滑动初始距离 399 s += s1 400 401 # 后退列表, 自定义后退滑动轨迹,必须是负值 402 back_list = [-1, -1, -2, -3, -2, -1, -1, -2, -3, -2, -1, -1] 403 404 return {'move_list': move_list, 'back_list': back_list} 405 406 def main(): 407 driver = webdriver.Chrome(r'D:\BaiduNetdiskDownload\chromedriver_win32\chromedriver.exe') 408 driver.implicitly_wait(10) 409 try: 410 driver.get('https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fwww.cnblogs.com%2F') 411 412 # 1、输入用户名与密码,并点击登录 413 user_input = driver.find_element_by_id('LoginName') 414 user_input.send_keys('_tank_') 415 time.sleep(0.2) 416 417 pwd_input = driver.find_element_by_id('Password') 418 pwd_input.send_keys('k46709394.') 419 time.sleep(2) 420 421 login_submit = driver.find_element_by_id('submitBtn') 422 login_submit.click() 423 424 # 2、获取完整的图片 425 image1 = get_image1(driver) 426 427 # 3、获取有缺口图片 428 image2 = get_image2(driver) 429 430 # 4、比对两张图片,获取滑动距离 431 distance = get_distance(image1, image2) 432 print(distance) 433 434 # 5、模拟人的滑动轨迹 435 move_dict = get_strck_move(distance) 436 # 获取前进滑动轨迹 437 move_list = move_dict['move_list'] 438 # 获取后退滑动轨迹 439 back_list = move_dict['back_list'] 440 441 # 6、开始滑动 442 move_tag = driver.find_element_by_class_name('geetest_slider_button') 443 # 点击摁住滑动按钮 444 ActionChains(driver).click_and_hold(move_tag).perform() 445 446 # 向前滑动 447 for move in move_list: 448 ActionChains(driver).move_by_offset(xoffset=move, yoffset=0).perform() 449 time.sleep(0.1) 450 451 time.sleep(0.1) 452 453 # 向后滑动 454 for back in back_list: 455 ActionChains(driver).move_by_offset(xoffset=back, yoffset=0).perform() 456 time.sleep(0.1) 457 458 # 制作微妙晃动 459 ActionChains(driver).move_by_offset(xoffset=3, yoffset=0).perform() 460 ActionChains(driver).move_by_offset(xoffset=-3, yoffset=0).perform() 461 462 time.sleep(0.1) 463 464 # 释放滑动按钮 465 ActionChains(driver).release().perform() 466 467 time.sleep(100) 468 469 finally: 470 driver.close() 471 472 if __name__ == '__main__': 473 main()