使用selenium进行滑动验证(会失败)首先 , 我们需要从html中获取滑块验证的图片 , 通过执行js , 将画布像素转为base64 , 然后python即可获取 , 进行拖拽处理:
from selenium import webdriverimport timeimport base64from PIL import Imagefrom io import BytesIOfrom selenium.webdriver.support.ui import WebDriverWaitdef checkVeriImage(driver):WebDriverWait(driver, 5).until(lambda driver: driver.find_element_by_css_selector('.geetest_canvas_bg.geetest_absolute'))time.sleep(1)im_info = driver.execute_script('return document.getElementsByClassName("geetest_canvas_bg geetest_absolute")[0].toDataURL("image/png");')# 拿到base64编码的图片信息im_base64 = im_info.split(',')[1]# 转为bytes类型im_bytes = base64.b64decode(im_base64)with open('./temp_bg.png', 'wb') as f:# 保存图片到本地 , 方便查看预览f.write(im_bytes)image_data = https://www.isolves.com/it/cxkf/yy/Python/2020-06-18/BytesIO(im_bytes)bgImage = Image.open(image_data)# 滑块距离左边有 5~10 像素左右误差offsetX = VeriImageUtil().getVerticalLineOffsetX(bgImage)eleDrag = driver.find_element_by_css_selector(".geetest_slider_button")action_chains = webdriver.ActionChains(driver)action_chains.drag_and_drop_by_offset(eleDrag,offsetX-10,0).perform()
貌似可以了 , 但实际上 , 验证时会遇到“拼图被怪物吃掉了 , 请重试” , 导致失败 。这是因为被检测到机器人(爬虫)操作了 。
避开人机识别B站滑块验证码的人机识别 , 其实不咋滴 , 主要靠是否存在停留间隔来判断 。一开始被网上文章误导 , 弄了什么距离=初速度乘以时间t + 1/2加速度乘以(时间平方)模拟拖拽 , 实际上是完全不对路的 。
文章插图
webdriver.ActionChains(driver).drag_and_drop_by_offset(eleDrag,offsetX-10,0).perform() 拖动滑块会导致验证失败 。在B站中 , 这是因为这个动作太快了的缘故 。有的同学就打算直接加 time.sleep(1) 了 , 这么做是不会成功的 , 会提示拼图被怪物吃掉了 , 请重试
实际上人做滑块验证的过程可以归为:手指快速拖拽验证码到指定位置 , 修正误差 , 停留一会儿 , 释放滑块 。
简单实现代码可以简单实现 , 都不需要模拟人修正拖拽误差的过程 , 普通网站不会去统计这个 , 至少B站不会 。
def simpleSimulateDragX(self, source, targetOffsetX):"""简单拖拽模仿人的拖拽:快速沿着X轴拖动 , 直接一步到达正确位置 , 再暂停一会儿 , 然后释放拖拽动作B站是依据是否有暂停时间来分辨人机的 , 这个方法适用 。:param source::param targetOffsetX::return: None"""#参考`drag_and_drop_by_offset(eleDrag,offsetX-10,0)`的实现 , 使用move方法action_chains = webdriver.ActionChains(self.driver)# 点击 , 准备拖拽action_chains.click_and_hold(source)action_chains.pause(0.2)action_chains.move_by_offset(targetOffsetX,0)action_chains.pause(0.6)action_chains.release()action_chains.perform()
添加修正过程的实现其实也就最后一段多出了fix的过程 , action_chains.move_by_offset(10,0)
def fixedSimulateDragX(self, source, targetOffsetX):#参考`drag_and_drop_by_offset(eleDrag,offsetX-10,0)`的实现 , 使用move方法action_chains = webdriver.ActionChains(self.driver)# 点击 , 准备拖拽action_chains.click_and_hold(source)action_chains.pause(0.2)action_chains.move_by_offset(targetOffsetX-10,0)action_chains.pause(0.6)action_chains.move_by_offset(10,0)action_chains.pause(0.6)action_chains.release()action_chains.perform()
终极版实现为了更像人类操作 , 可以进行拖拽间隔时间和拖拽次数、距离的随机化 。虽然这对B站没什么用 , 还可能会导致验证时间变久一些 。拖拽多次 , 可以使用循环遍历 , 不过代码可能不好理解 , 直接判断就行 , 最多也就两到3次就完成修正误差的过程 。
def __getRadomPauseScondes(self):""":return:随机的拖动暂停时间"""return random.uniform(0.6, 0.9)def simulateDragX(self, source, targetOffsetX):"""模仿人的拖拽动作:快速沿着X轴拖动(存在误差) , 再暂停 , 然后修正误差防止被检测为机器人 , 出现“图片被怪物吃掉了”等验证失败的情况:param source:要拖拽的html元素:param targetOffsetX: 拖拽目标x轴距离:return: None"""action_chains = webdriver.ActionChains(self.driver)# 点击 , 准备拖拽action_chains.click_and_hold(source)# 拖动次数 , 二到三次dragCount = random.randint(2, 3)if dragCount == 2:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 修正误差 , 防止被检测为机器人 , 出现图片被怪物吃掉了等验证失败的情况action_chains.move_by_offset(-sumOffsetx, 0)elif dragCount == 3:# 总误差值sumOffsetx = random.randint(-15, 15)action_chains.move_by_offset(targetOffsetX + sumOffsetx, 0)# 暂停一会action_chains.pause(self.__getRadomPauseScondes())# 已修正误差的和fixedOffsetX = 0# 第一次修正误差if sumOffsetx < 0:offsetx = random.randint(sumOffsetx, 0)else:offsetx = random.randint(0, sumOffsetx)fixedOffsetX = fixedOffsetX + offsetxaction_chains.move_by_offset(-offsetx, 0)action_chains.pause(self.__getRadomPauseScondes())# 最后一次修正误差action_chains.move_by_offset(-sumOffsetx + fixedOffsetX, 0)action_chains.pause(self.__getRadomPauseScondes())else:raise Exception("莫不是系统出现了问题?!")# 参考action_chains.drag_and_drop_by_offset()action_chains.release()action_chains.perform()
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Python 还能实现哪些 AI 游戏?附上代码一起来一把
- 数据更新删除与排序:横向对比 Python、PowerBI、Excel、MySQL
- 用 Python 解析命令行参数
- 用 Python 绘制数据的7种最流行的方法
- 如何监视Python程序的内存使用情况
- 科学家破解机体再生密码
- 5个案例让Python输出漂亮的表格
- Python 命令行之旅:使用 argparse 实现 git 命令
- 使用Streamlit从简单的Python脚本创建交互式WebApp
- 家居风水布局禁忌中心受污的破解方法