等距滑块验证码破解
抓取数据的时候,有时候会碰到滑块验证码,比如说某瓣。我们尝试用selenium拖拽的方式去通过验证,但是此方法只适用于滑块和缺口等距时的情况。由于此方法适用于所有等距滑块验证码的破解,所以在此就直接上代码了。
1、导入selenium及动作链
import time
from selenium import webdriver
# 导入动作链
from selenium.webdriver.common.action_chains import ActionChains
2、访问目标url
# 调用浏览器
driver = webdriver.Chrome(executable_path=r'./webdriver/chromedriver.exe')
# 最大化浏览器
driver.maximize_window()
# 访问目标url
driver.get(url='https://www.douban.com/')
3、输入账号密码点击登录
此处会出现一个xpath无法定位密码登录区域的问题,原因是密码登录框被嵌套进一个子页面当中了,需要先切入到子页面中,再点击密码登录。
# switch_to.frame(0) : 0代表的是第一个子页面
driver.switch_to.frame(0)
driver.find_element_by_xpath('/html/body/div[1]/div[1]/ul[1]/li[2]').click()
# 查找并输入账号
driver.find_element_by_xpath('//*[@id="username"]').send_keys('13355889940')
# 查找并输入密码
driver.find_element_by_xpath('//*[@id="password"]').send_keys('11111111')
# 查找并点击登录按钮
driver.find_element_by_xpath('/html/body/div[1]/div[2]/div[1]/div[5]').click()
4、获取并移动滑块
此处又会出现一个iframe嵌套的子页面,所以仍然需要先进入到子页面中,再用selenium定位元素。iframe是常见的导致selenium无法定位元素的问题之一。
driver.switch_to.frame(1)
time.sleep(2)
# 获取滑块
block = driver.find_element_by_id('tcaptcha_drag_thumb')
# click_and_hold() 点击并保持点击状态
# on_element:将此状态加载到哪一个元素身上
# perform():执行
ActionChains(driver).click_and_hold(on_element=block).perform()
# 移动滑块
# move_by_offset()
# xoffset:横向移动距离
# yoffset:纵向移动距离
# 因为是等距的,所以xoffset的值就是滑块到缺口的距离
ActionChains(driver).move_by_offset(xoffset=175, yoffset=0).perform()
- 试了几次,发现出提示网络恍惚了一下,请重试。可能是被对方检测到了是机器人在模拟登陆
- 解决办法,拖动滑块的时候模拟人的操作,定义一个计算轨迹的方法
def geTracks(distance):
"""
定义方法计算移动轨迹
先匀加速,后匀减速
"""
# 定义初速度
v = 0
# 定义单位时间
t = 0.1
# 定义存放运动轨迹的列表
tracks = []
# 定义当前位移
current = 0
# 定义匀加速运动和匀减速运动的分界
mid = distance * 4 / 5
while current < distance:
# 未到达分界点时,加速度大于0,做匀加速运动
if mid > current:
a = 2
# 达到分界点时,做匀减速运动
else:
a = -3
v0 = v
# 计算位移
x = v * t + 1 / 2 * a * t ** 2
# 计算滑块当前位移
current += x
# 计算初速度
v = v0 + a * t
tracks.append(x)
return tracks
5、用动作链的move_by_offset执行上述方法获取到的偏移量,模拟人工拖动滑块
tracks = getTracks(75)
for track in tracks_list:
ActionChains(driver).move_by_offset(xoffset=track, yoffset=0).perform()
# 停1秒释放鼠标:release()
time.sleep(1)
ActionChains(driver).release().perform()
成功通过等距滑块验证,上述方法可以用于所有的等距滑块验证码破解。