0


python selenium模块联合带带弟弟破解滑块验证码

兄弟们肯定在搞爬虫时经常遇到滑块验证码的反爬措施,这苦恼了我几天,好在有dddd和selenium模块助我前行

第一个函数是登录函数,主要就是输入用户名和密码后自动弹出滑块验证码

主要用到selenium模块

导入模块:

from selenium import webdriver

from selenium.webdriver.common.by import By

知识点:

drive = webdriver.Firefox()

#创建实例,浏览器为火狐

element = driver.find_element(By.XPATH,"这里锁定元素输入xpath路径就行")

#利用By.XPATH锁定元素当然还有By.CLASSNAME、By.ID等等,提供不同元素名锁定元素

element.send_keys("111")

#向锁定的element元素输入111值

element.click()

#点击该元素

如果遇到同一CLASSBNAME有两个元素

可以使用

element = driver.find_elements(By.CLASSNAME)[1]

这样的方式锁定第二个元素位置 注意:element后面有个s

  1. def login(driver,uname,pwd):
  2. """
  3. 某系统登录框输入手机号和密码,并点击成功
  4. """
  5. driver.get("https://user.xxxx.com/user/ut=1&style=1#/pages/white-hat/login/login")
  6. # 等待页面加载完成,设置超时停止加载
  7. try:
  8. driver.set_page_load_timeout(10)
  9. except:
  10. pass
  11. # 点击同意按钮
  12. ty = driver.find_element(By.XPATH,"/html/body/div/div/div[2]/div[2]/div/div[1]/div[2]/div/div[1]/div/div[2]/div[1]/div[1]/form/div[3]/label/span[1]/span")
  13. ty.click()
  14. #输入手机号
  15. phone = driver.find_element(By.XPATH,"/html/body/div/div/div[2]/div[2]/div/div[1]/div[2]/div/div[1]/div/div[2]/div[1]/div[1]/form/div[1]/div/div[2]/input")
  16. phone.send_keys(uname)
  17. #输入密码
  18. passwd = driver.find_element(By.XPATH,"/html/body/div/div/div[2]/div[2]/div/div[1]/div[2]/div/div[1]/div/div[2]/div[1]/div[1]/form/div[2]/div/div[2]/input")
  19. passwd.send_keys(pwd)
  20. #点击登录
  21. dl = driver.find_element(By.XPATH,"/html/body/div/div/div[2]/div[2]/div/div[1]/div[2]/div/div[1]/div/div[2]/div[1]/div[1]/form/div[4]/div/button")
  22. dl.click()

接下来silder_imgs函数主要是提取出滑动模块的三个图片,主要是为了计算移动距离而准备

  1. def slider_imgs(driver):
  2. """
  3. 保存每次滑动验证码的三个图片
  4. """
  5. #定位背景图元素的位置
  6. active = True
  7. while active:
  8. try:
  9. time.sleep(1)
  10. img_element = driver.find_element(By.XPATH,"/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/div/canvas[1]")
  11. hk_element = driver.find_element(By.XPATH,"/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/div/canvas[2]")
  12. yt_element = driver.find_element(By.XPATH,"/html/body/div[2]/div[2]/div[6]/div/div[1]/div[1]/div/a/div[1]/canvas")
  13. active = False
  14. except:
  15. continue
  16. # 执行js 获取改元素的data:url
  17. img_data_b64 = driver.execute_script("return arguments[0].toDataURL('image/png').substring(22);",img_element)
  18. hk_data_b64 = driver.execute_script("return arguments[0].toDataURL('image/png').substring(22);",hk_element)
  19. yt_data_b64 = driver.execute_script("return arguments[0].toDataURL('image/png').substring(22);",yt_element)
  20. #解码
  21. img_data = base64.b64decode(img_data_b64)
  22. hk_data = base64.b64decode(hk_data_b64)
  23. yt_data = base64.b64decode(yt_data_b64)
  24. #以二进制保存
  25. with open("./imgs/bg.png","wb") as f:
  26. f.write(img_data)
  27. #print("[*]滑块验证码背景图已保存")
  28. with open("./imgs/hk.png","wb") as f:
  29. f.write(hk_data)
  30. #print("[*]滑块验证码滑块图片已保存")
  31. with open("./imgs/yt.png","wb") as f:
  32. f.write(yt_data)
  33. #print("[*]滑块验证码原图已保存")
  34. print("[*]保存滑动验证码成功")

提取出来如下图所示,(hk_jg.png是下一个模块处理后的结果,不用管)

计算距离的主要需要图片就是通过hk.png处理后的hk_jg.png和bg.png两个图片

接下来处理hk.png为hk_jg.png

直接传入hk.png这种图片的路径,可以实现将带有白框的图片截取成只有图片的最小方框,例如:

这么多白框的图片变成下图这种

代码实现如下所示

  1. def hk_chuli(hk_img):
  2. """
  3. 处理滑块图片
  4. :return:
  5. """
  6. image = Image.open(hk_img) # 打开tiff图像
  7. ImageArray = np.array(image)
  8. row = ImageArray.shape[0]
  9. col = ImageArray.shape[1]
  10. # 先计算所有图片的裁剪范围,然后再统一裁剪并输出图片
  11. x_left = row
  12. x_top = col
  13. x_right = 0
  14. x_bottom = 0
  15. for r in range(row):
  16. for c in range(col):
  17. # if ImageArray[row][col][0] < 255 or ImageArray[row][col][0] ==0:
  18. if ImageArray[r][c][0] < 255 and ImageArray[r][c][0] != 0: # 外框有个黑色边框,增加条件判断
  19. if x_top > r:
  20. x_top = r # 获取最小x_top
  21. if x_bottom < r:
  22. x_bottom = r # 获取最大x_bottom
  23. if x_left > c:
  24. x_left = c # 获取最小x_left
  25. if x_right < c:
  26. x_right = c # 获取最大x_right
  27. #print(x_left, x_top, x_right, x_bottom)
  28. cropped = image.crop((x_left - 5, x_top - 5, x_right + 5, x_bottom + 5)) # (left, upper, right, lower)
  29. cropped.save(r".\imgs\{}.png".format("hk_jg"))
  30. print("[*]处理滑块图片成功")

现在开始引入带带弟弟(ddddocr)模块计算滑动距离了

模块引用:
import ddddocr

知识点:

det = ddddocr.Dddd0cr(det=False,show_ad=False)

#创建实例

det.slide_match(hk_jg,bgsimple_target=True)

#传入处理好的滑块图片和有缺口的背景图片,实现计算距离,准确度很高,但是可能固定查5左右,要自己调试

  1. def get_len(hk,bg):
  2. """
  3. 调用ddddocr获取滑动距离
  4. """
  5. det = ddddocr.DdddOcr(det=False,ocr=False,show_ad=False)
  6. with open(hk,"rb") as f:
  7. hk = f.read()
  8. with open(bg,"rb") as f:
  9. bg = f.read()
  10. res = det.slide_match(hk,bg,simple_target=True)
  11. return res["target"][0]

下一步就是利用selenium模块拖动滑块元素移动了

具体解释都在代码块里,这里再提一点,由于极验的滑块验证码会检验鼠标轨迹,所以必须模拟人手的鼠标滑动轨迹,所以我搞了一个加速的函数

get_tracks就是加速函数,这个函数各位直接拿去用就行,不用理解,在自动滑动的时候引用就行

  1. def get_tracks(distance):
  2. """
  3. 拿到移动轨迹,模拟人的滑动行为,先匀加速后匀减速
  4. 匀变速运动基本公式:
  5. 1.v=v₀+at
  6. 2.s=v₀t+1/2*at²
  7. :param distance:滑块一次性快速移动到某一位置后剩下的距离,进行五等分
  8. :return:位置/轨迹列表,列表内的一个元素代表0.3s的位移
  9. """
  10. v = 0 # 初速度
  11. t = 0.3 # 单位时间为0.3s来统计轨迹,轨迹即0.3内的位移
  12. tracks = [] # 位置/轨迹列表,列表内的一个元素代表0.3s的位移
  13. current = 0 # 当前的位移
  14. mid = distance * 4 / 5 # 到达mid值开始减速,前4/5匀加速,后1/5匀减速
  15. while current < distance:
  16. if current < mid: # 加速度越小,单位时间内的位移越小,模拟的轨迹就越多越详细
  17. a = 2
  18. else:
  19. a = -3
  20. v0 = v # 初速度
  21. s = v0 * t + 0.5 * a * (t ** 2) # 0.3s内的位移
  22. current += s # 当前的位置
  23. tracks.append(round(s)) # 添加到轨迹列表
  24. v = v0 + a * t # 速度已经达到v,该速度作为下次的初速度
  25. return tracks # tracks:[第1个0.3s的移动距离,第2个0.3s的移动距离,......]

滑动函数如下所示

  1. def slider_verification_code(driver,length):
  2. """
  3. 滑动滑块验证码
  4. """
  5. #按住滑块按钮
  6. silder = driver.find_element(By.XPATH,"/html/body/div[2]/div[2]/div[6]/div/div[1]/div[2]/div[2]")
  7. # 创建鼠标动态链,
  8. subiao = ActionChains(driver)
  9. # 点击指定元素并保持
  10. subiao.click_and_hold(on_element=silder).perform()
  11. # 滑动指定单位 xoffset代表水平方向的移动 正数为向右
  12. subiao.move_to_element_with_offset(to_element=silder,xoffset=15,yoffset=15).perform()
  13. time.sleep(0.5)
  14. #使用加速度
  15. tracks = get_tracks(length-15)
  16. for track in tracks:
  17. subiao.move_by_offset(xoffset=track,yoffset=0).perform()
  18. # 放开鼠标
  19. time.sleep(1)
  20. subiao.release().perform()
  21. #网络不给力情况
  22. try:
  23. continue_element = driver.find_element(By.XPATH, "/html/body/div[2]/div[2]/div[4]/div[3]")
  24. if continue_element:
  25. print("[*]出现网络不给力情况,立马开始重试")
  26. continue_element.click()
  27. main()
  28. except:
  29. pass
  30. # 没绕过情况
  31. try:
  32. #检测滑动验证码是否还存在
  33. huadon = driver.find_element(By.CLASS_NAME,"geetest_slider_button")
  34. if huadon:
  35. # 刷新
  36. sx = driver.find_element(By.XPATH, "/html/body/div[2]/div[2]/div[6]/div/div[2]/div/a[2]")
  37. sx.click()
  38. print("[*]绕过滑动验证码失败,开始下一次尝试\n")
  39. main()
  40. try:
  41. #检测是否出现多次尝试失败情况
  42. hk_anniu_element = driver.find_element(By.CLASS_NAME,"geetest_slider_button")
  43. except:
  44. print("[*]ERROR:多次尝试绕过验证码失败,立马开始重试\n")
  45. conshi_element = driver.find_element(By.XPATH,"/html/body/div[2]/div[2]/div[4]/div[3]")
  46. conshi_element.click()
  47. time.sleep(2)
  48. main()
  49. except:
  50. print("[*]滑动验证码bypass成功\n")
  51. pass

破解效果视频如下所示

滑动验证码绕过效果视频


本文转载自: https://blog.csdn.net/weixin_67289581/article/details/137020217
版权归原作者 网安_秋刀鱼 所有, 如有侵权,请联系我们删除。

“python selenium模块联合带带弟弟破解滑块验证码”的评论:

还没有评论