selenium解决滑块验证码

方法一:比较稳定

代码:

# encoding: utf-8
# @File  : Sliders.py
# @Author: wu shaofan
# @Date  :  2024/02/11
# @Desc : 封装滑动验证码
import os
import time
import cv2
import numpy as np
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import conftest


# Sliders(滑动条)
class Sliders:
    def __init__(self, path):
        self.url = path
        # 设置 Chrome WebDriver 路径
        chrome_driver_path = conftest.BASE_DIR + '/tool/chromedriver.exe'
        # 创建 ChromeOptions 对象
        self.options = Options()
        self.options.add_experimental_option("excludeSwitches", ["enable-logging"])
        # 创建 Chrome WebDriver 服务
        service = Service(chrome_driver_path)
        # 创建 Chrome WebDriver 实例
        self.driver = webdriver.Chrome(service=service, options=self.options)
        # 窗口最大化
        self.driver.maximize_window()
        # 打开网页
        self.driver.get(url)
        # 点击 可疑用户-滑动拼图
        loc = 'ul[class="tcapt-tabs__container"] li[captcha-type="jigsaw"]'
        self.driver.find_element('css selector', loc).click()
        # 滚动页面滑动条,让滑块显示出来
        js = 'document.documentElement.scrollTop=200'
        self.driver.execute_script(js)
        time.sleep(1)
        # 点击完成验证按钮
        loc = 'span[class="yidun_intelli-text"]'
        self.driver.find_element('css selector', loc).click()

    # 保存验证码背景图和滑块图
    def save_image(self):
        time.sleep(2)
        # 小图片
        url_s = self.driver.find_element('class name', 'yidun_jigsaw').get_attribute('src')
        # 大图片
        url_b = self.driver.find_element('class name', 'yidun_bg-img').get_attribute('src')
        header = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'}
        # 发送请求,获取验证码图片
        response_s = requests.get(url_s, headers=header).content
        response_b = requests.get(url_b, headers=header).content

        # 判断文件夹是否存在不存在则创建'
        os.makedirs('./image/', exist_ok=True)
        # 保存图片
        with open('./image/slider_s.png', 'wb') as f:
            f.write(response_s)

        with open('./image/slider_b.png', 'wb') as f:
            f.write(response_b)

    # 将两张图片先进行灰度处理,再对图像进行高斯处理,最后进行边缘检测
    def handel_img(self, img):
        imgGray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)  # 转灰度图
        imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)  # 高斯模糊
        imgCanny = cv2.Canny(imgBlur, 60, 60)  # Canny算子边缘检测
        return imgCanny

    # 将JPG图像转变为4通道(RGBA)
    def add_alpha_channel(self, img):
        """ 为jpg图像添加alpha通道 """
        r_channel, g_channel, b_channel = cv2.split(img)  # 剥离jpg图像通道
        # 创建Alpha通道
        alpha_channel = np.ones(b_channel.shape, dtype=b_channel.dtype) * 255
        # 融合通道
        img_new = cv2.merge((r_channel, g_channel, b_channel, alpha_channel))
        return img_new

    # 读取图像
    def match(self, img_s_path, img_b_path):
        # 读取图像
        img_jpg = cv2.imread(img_s_path, cv2.IMREAD_UNCHANGED)
        img_png = cv2.imread(img_b_path, cv2.IMREAD_UNCHANGED)
        # 判断jpg图像是否已经为4通道
        if img_jpg.shape[2] == 3:
            img_jpg = self.add_alpha_channel(img_jpg)
        img = self.handel_img(img_jpg)
        small_img = self.handel_img(img_png)
        res_TM_CCOEFF_NORMED = cv2.matchTemplate(img, small_img, 3)
        value = cv2.minMaxLoc(res_TM_CCOEFF_NORMED)
        value = value[3][0]  # 获取到移动距离
        return value

    # 移动
    def move(self, distance):
        # 获取滑块元素
        loc = 'div[class="yidun_slider  yidun_slider--hover "]'
        ele = self.driver.find_element('css selector', loc)
        # 实例化对象
        action = ActionChains(self.driver)
        # 拖动滑块

        action.drag_and_drop_by_offset(ele, xoffset=distance, yoffset=0).perform()

        # 定位到验证成功
        #这里 如果写time.sleep(2)会匹配失败,具体原因不知道
        time.sleep(1)
        loc = '.yidun_tips__text.yidun-fallback__tip'
        text = self.driver.find_element('css selector',loc).text

        if text == "验证成功":
            print("验证成功")
        else:
            print("验证失败")


if __name__ == '__main__':
    url = "https://dun.163.com/trial/sense"
    obj = Sliders(url)
    # 1、下载两张图片
    obj.save_image()
    # 2、对比两张图片,计算忽距离
    small_img = './image/slider_s.png'  # 滑块图(小图片)
    big_img = './image/slider_b.png'   # 背景图(大图片)
    distance = obj.match(small_img, big_img)
    distance = distance / 320 * 300 + 12
    # 3. 移动
    obj.move(distance)

解释:

为啥  distance = distance / 320 * 300 + 12

因为会匹配失败

这里有以下两点原因:

  1. 图片尺寸发生了变化,距离要进行转换。
  2. 滑块滑动时,滑块和残缺块的相对位置有变动。

首先解决图片尺寸变化问题,找到网页中图片大小:300*150.5

保存到本地的尺寸:320*160

 所以要对距离进行以下处理:

	distance = distance / 320 * 300

关于第二个问题,这里没有找到很好的测量工具测量出来,好在验证码对位置精确度要求不高,就一个个试数吧。

 

	distance = distance /320 * 300 + 12
distance = distance / 320 * 300 + 10  
distance = distance / 320 * 300 + 9
也可以成功,我试下,大概范围在 【5,14】之内(包括5和14)都可以匹配成功

方法二: 会定位失败,所以用循环

代码

# encoding: utf-8
# @File  : test01.py
# @Author: wu shaofan
# @Desc : 处理滑动块
# @Date  :  2024/02/07
import os
import time
import cv2
import numpy as np
import requests
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
import conftest

# 设置 Chrome WebDriver 路径
chrome_driver_path = conftest.BASE_DIR + '/tool/chromedriver.exe'

# 创建 ChromeOptions 对象
options = Options()
options.add_experimental_option("excludeSwitches", ["enable-logging"])

# 创建 Chrome WebDriver 服务
service = Service(chrome_driver_path)

# 创建 Chrome WebDriver 实例
driver = webdriver.Chrome(service=service, options=options)

# 窗口最大化
driver.maximize_window()

# 打开网页
url = "https://dun.163.com/trial/sense"
driver.get(url)

# 点击进入滑块界面
loc = 'ul[class="tcapt-tabs__container"] li[captcha-type="jigsaw"]'
driver.find_element('css selector',loc).click()
# 滚动页面滑动条,让滑块显示出来
js = 'document.documentElement.scrollTop=200'
driver.execute_script(js)
time.sleep(1)
# 点击完成验证
loc = 'span[class="yidun_intelli-text"]'
driver.find_element('css selector',loc).click()
time.sleep(3)

while True:
    # 获取两张图片
    url_s = driver.find_element('class name','yidun_jigsaw').get_attribute('src')
    url_b = driver.find_element('class name' ,'yidun_bg-img').get_attribute('src')
    headers = {
        'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.41 Safari/537.36'
    }
    res_s = requests.get(url_s, headers=headers)
    data_s = res_s.content
    res_b = requests.get(url_b, headers=headers)
    data_b = res_b.content

    # 判断文件夹是否存在不存在则创建'
    os.makedirs('./image/', exist_ok=True)

    # 保存图片
    with open('./image/pic_s.png', 'wb') as f:
        f.write(data_s)
    with open('./image/pic_b.png', 'wb') as f:
        f.write(data_b)

    # 使用opencv读取两张图片
    simg = cv2.imread('./image/pic_s.png')
    bimg = cv2.imread('./image/pic_b.png')

    # 灰度处理,降低偏差
    s_img = cv2.cvtColor(simg, cv2.COLOR_BGR2GRAY)
    b_img = cv2.cvtColor(bimg, cv2.COLOR_BGR2GRAY)

    # 保存两张的灰度处理的图片
    cv2.imwrite('./image/hui_simg.png', s_img)
    cv2.imwrite('./image/hui_bimg.png', b_img)

    # 处理滑块图片,保存有效部分
    s_img = s_img[s_img.any(1)]

    # opencv的匹配算法,匹配模块寻找两张图片的相似之处
    result = cv2.matchTemplate(b_img, s_img, cv2.TM_CCOEFF_NORMED)
    #print('result', result)

    # 获取坐标
    # 获取最大索引
    index_max = np.argmax(result)
    # 获取到坐标
    y, x = np.unravel_index(index_max, result.shape)
    #print("y:", y, "x:", x)

    # 定位到滑块
    loc = '.yidun_slider.yidun_slider--hover'
    ele = driver.find_element('css selector',loc)
    # 实例化对象
    action = ActionChains(driver)
    # 拖动滑块
    time.sleep(1)
    action.drag_and_drop_by_offset(ele, xoffset=x, yoffset=0).perform()
    time.sleep(1)
    # 定位到验证成功
    time.sleep(1)
    loc = '.yidun_tips__text.yidun-fallback__tip'
    text = driver.find_element('css selector',loc).text
    if text == "验证成功":
        break

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
滑块验证码是一种常见的人机验证方式,常用于网站注册、登录等场景中。使用selenium模拟鼠标操作可以解决滑块验证码的验证问题。以下是一个滑块验证码selenium解决方案: 1. 打开页面,找到滑块验证码的位置和滑块的元素。 2. 获取滑块滑块背景的坐标位置。 3. 计算滑块需要移动的距离。 4. 使用selenium模拟鼠标按下滑块,移动滑块,松开滑块的操作,通过ActionChains类来实现。 5. 判断是否验证成功。 以下是示例代码: ``` from selenium import webdriver from selenium.webdriver.common.action_chains import ActionChains import time url = "http://www.xxx.com" driver = webdriver.Chrome() driver.get(url) # 找到滑块滑块背景的元素 slider = driver.find_element_by_xpath("xxx") slider_bg = driver.find_element_by_xpath("xxx") # 获取滑块滑块背景的坐标位置 slider_location = slider.location slider_bg_location = slider_bg.location # 计算滑块需要移动的距离 distance = slider_bg_location['x'] + slider.size['width'] - slider_location['x'] - slider.size['width'] / 2 # 使用selenium模拟鼠标按下滑块,移动滑块,松开滑块的操作 ActionChains(driver).click_and_hold(slider).perform() ActionChains(driver).move_by_offset(distance, 0).perform() ActionChains(driver).release().perform() # 等待验证结果 time.sleep(3) # 判断是否验证成功 if driver.current_url == url: print("验证成功") else: print("验证失败") ``` 需要根据实际情况修改代码中的xpath和url等参数,以适应不同的滑块验证码场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值