登录163邮箱的滑块验证
登录163网易邮箱取数功能,查阅了很多博客的代码都不太稳定或者已失效,下面是经过修改的一个方案,成功率大概在90%以上
bash
def get_verify(self, name='处理滑块移动'):
max_distance = self.handle_picture()
reality_distance = int((max_distance - 64) / 1.45)
sleep(0.5)
track_list = self.handle_tracks(reality_distance)
# 获取滑块元素
slider_handle = self.driver.find_element(By.XPATH, '//*[@class="yidun_slider"]')
ActionChains(self.driver).click_and_hold(slider_handle).perform()
for i in track_list:
ActionChains(self.driver).move_by_offset(i, 0).perform()
sleep(1)
ActionChains(self.driver).release().perform()
def handle_picture(self):
bg_img = re.findall(r'alt="验证码背景".*?src="(.*?)"', self.driver.page_source)[0]
hk_img = re.findall(r'alt="验证码滑块".*?src="(.*?)"', self.driver.page_source)[0]
with open('./bg_img.jpg', 'wb') as f:
f.write(requests.get(bg_img).content)
f.close()
with open('./hk_img.png', 'wb') as f:
f.write(requests.get(hk_img).content)
f.close()
# 读取背景图片和缺口图片
bg_img = cv2.imread('./bg_img.jpg') # 背景图片
tp_img = cv2.imread('./hk_img.png') # 缺口图片
# 识别图片边缘
bg_edge = cv2.Canny(bg_img, 100, 200)
tp_edge = cv2.Canny(tp_img, 100, 200)
# 转换图片格式
bg_pic = cv2.cvtColor(bg_edge, cv2.COLOR_GRAY2RGB)
tp_pic = cv2.cvtColor(tp_edge, cv2.COLOR_GRAY2RGB)
# 缺口匹配
res = cv2.matchTemplate(bg_pic, tp_pic, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res) # 寻找最优匹配
x = max_loc[0] # 滑块在验证图片的x坐标(左边)
# 绘制方框
th, tw = tp_pic.shape[:2]
tl = max_loc # 左上角点的坐标
br = (tl[0] + tw, tl[1] + th) # 右下角点的坐标
cv2.rectangle(bg_img, tl, br, (0, 0, 255), 2) # 绘制矩形
# cv2.imwrite(r'C:\test\out.jpg', bg_img) # 保存在本地
return int(br[0])
@staticmethod
def handle_tracks(distance):
t = 0.1
speed = 0
current = 0
mid = 3 / 5 * distance
track_list = []
while current < distance:
if current < mid:
# a = random.choice([1, 2, 3])
a = 3
else:
# a = random.choice([-1, -2, -3])
a = -4
move_track = speed * t + 0.5 * a * t ** 2
track_list.append(round(move_track))
speed = speed + a * t
current += move_track
# 模拟人类来回移动了一小段
end_track = [1, 0] * 10 + [0] * 10 + [-1, 0] * 10
track_list.extend(end_track)
offset = sum(track_list) - distance
# 由于四舍五入带来的误差,这里需要补回来
if offset > 0:
track_list.extend(offset * [-1, 0])
elif offset < 0:
track_list.extend(offset * [1, 0])
return track_list