0


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

本文转载自: https://blog.csdn.net/weixin_44791664/article/details/136096609
版权归原作者 吴少凡 所有, 如有侵权,请联系我们删除。

“selenium解决滑块验证码”的评论:

还没有评论