以查询shunfeng快递为例子,使用selenium来进行滑块的验证
# 显示等待
wait = WebDriverWait(driver, 30)
# 等待验证码模块加载完成
wait.until(EC.presence_of_element_located((By.ID, 'tcaptcha_iframe')))
# 切换iframe
driver.switch_to.frame('tcaptcha_iframe')
# 等待图片加载完成
wait.until(EC.presence_of_element_located((By.ID, 'slideBg')))
# 然后就可以定位提取url进行图片的保存
使用opencv可以很好的解决
pip install opencv-python
def get_long():
# 背景图片处理
# 灰度图片
bg_img = cv2.imread('cpt1.png', 0)
# 高斯滤波,模糊化
bg_img = cv2.GaussianBlur(bg_img, (3, 3), 0)
# 边缘检测, 后两个参数为阈值,一般50,150即可
bg_img = cv2.Canny(bg_img, 50, 150)
slide_img = cv2.imread('cpt2.png', 0)
slide_img = cv2.GaussianBlur(slide_img, (3, 3), 0)
slide_img = cv2.Canny(slide_img, 50, 150)
# 寻找最佳匹配
res = cv2.matchTemplate(bg_img, slide_img, cv2.TM_CCORR_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
top_left = max_loc[0]
return top_left
def get_track(distance):
# 记录滑动轨迹
tracks = []
# 从0开始
current = 0
# 何时开始减速
mid = distance*4/5
# 时间
t = 0.2
# 速度
v = 0
while current < distance:
# 加速度
if current < mid:
a = 3
else:
a = -3
v0 = v
v = v0 + a*t
move = v0*t + 1/2 * a * t * t
tracks.append(round(move))
current += move
tracks.append(distance-sum(tracks))
return tracks
distance即为要滑动的距离,传参数时还需要减去滑块本身所处位置的距离
# 按钮定位
button = driver.find_element_by_id('tcaptcha_drag_button')
# 事件处理
webdriver.ActionChains(driver).click_and_hold(button).perform()
# 按照轨迹滑动,perform() 依次执行任务
for t in tmp_track:
webdriver.ActionChains(driver).move_by_offset(xoffset=t, yoffset=0).perform()
# 释放按钮
webdriver.ActionChains(driver).release(button).perform()
以qidian登陆为例,这里可以看到是无法单独获取到滑块图片,和之前不同的是图片的获取和获取滑动距离,其他都一致
还是和之前一样,等待滑动验证码的加载完成,这里就不多做注释
wait = WebDriverWait(browser, 30)
wait.until(EC.presence_of_element_located((By.ID, 'loginIfr')))
browser.switch_to.frame('loginIfr')
browser.find_element_by_xpath('//*[@id="username"]').send_keys('qeqwewd')
browser.find_element_by_xpath('//*[@id="password"]').send_keys('qweqwe')
browser.find_element_by_xpath('//*[@id="j-inputMode"]/div[2]/a').click()
wait.until(EC.presence_of_element_located((By.ID, 'tcaptcha_iframe_dy')))
browser.switch_to.frame('tcaptcha_iframe_dy')
# 定位截屏得到图片
browser.find_element_by_id('slideBg').screenshot('captch.png')
def get_long():
bg_img = cv2.imread('captch.png', 0)
bg_img = cv2.GaussianBlur(bg_img, (3, 3), 0)
canny = cv2.Canny(bg_img, 220, 500)
# 图象的边缘显示
# cv2.imshow('Canny', canny)
# cv2.waitKey(10000)
# 轮廓检测
contours, hierarchy = cv2.findContours(canny, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
for i, contour in enumerate(contours): # 所有轮廓
# 面积和周长,可以找一个区间尝试
if 500 < cv2.contourArea(contour) <= 2000 and 100 < cv2.arcLength(contour, True) < 300:
# 外接矩形,x,y是矩形左上角的坐标,w,h为宽高
x, y, w, h = cv2.boundingRect(contour)
# print(x, y, w, h)
# 绘制矩形
# cv2.rectangle(bg_img, (x, y), (x + w, y + h), (0, 0, 255), 2)
# cv2.imshow('image', bg_img)
# cv2.waitKey(10000)
# 找目标缺口,第一个可能是滑块
if x <= 200:
continue
return int(x-30)
后面就是计算模仿人类移动轨迹,然后进行按钮定位进行滑动即可
这里获取到图片后可以使用pillow来获取滑动的距离
from PIL import Image, ImageChops
img_a = Image.open(path)
img_b = Image.open(path)
x = ImageChops.difference(img_a, img_b).getbbox()
x为缺口坐标(left, top, right, bottom)
x[0]即为滑动的距离,记得要减去滑块之前的距离