京东最新滑块验证-selenium

作者分享京东滑块验证的解决过程,指出滑动轨迹和滑动距离是两大难点。对于滑动距离,用cv2识别计算通过率低,改用深度学习模型自测通过率超80%。还搭建Flask接口方便调用模型,最后提供源码供交流学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   

这段时间一直在做京东滑块验证,也翻阅大量博客,我认为有两处难点:

  • 滑动轨迹
    • 京东将大量模拟人为的轨迹方程都被封了,导致即使对齐也无法通过验证。
  • 滑动距离
    • 经过翻阅博客,发现大多数博客采用的方法是通过cv2识别计算出滑动距离,这个方法通过率并不高(可能是我技术有限,使用cv2方式一次都没通过)。

滑动轨迹自然不必多说,网上一搜一大堆,我使用的是模拟人为加速度,最后滑超一点然后滑动回来(代码放在后面)

滑动距离,一开始使用cv2搞了一整天一次也没通过,最后改用深度学习模型,自测通过率超过80%,废话不多说直接看成果。

JD_1

首先下载滑动背景图作为模型训练输入,训练好模型后为了方便调用,搭建Flask接口,其次下载背景图调用模型API接口,将图片作为推理输入,这里注意:京东滑动背景图是base64格式,需要先解码保存,随后传入模型进行推理。

# 推理函数
def requests_img(base):
    image_base64 = base[22:]
    imgdata = base64.b64decode(image_base64)  # base64解码
    with open(f"images/test.png", 'wb') as f:
        f.write(imgdata)
    data = {
        'image': open('images/test.png', 'rb')
    }
    data = requests.post('http://127.0.0.1:5000/upload', files=data)  # 将图片传入API接口获得缺口左上和右下角缺口

    return data.json().get('result').get('xmin')*0.82  # 下载的图片和网站上预览图片大小不一致,所以需要设置偏移




# 移动轨迹函数
def get_track8(distance):
    # 移动轨迹
    tracks = []
    # 当前位移
    current = 0
    # 减速阈值
    mid = distance * 4 / 5
    # 时间间隔
    t = 0.2
    # 初始速度
    v = 0

    while current < distance:
        if current < mid:
            a = random.uniform(2, 5)
        else:
            a = -(random.uniform(12.5, 13.5))
        v0 = v
        v = v0 + a * t
        x = v0 * t + 1 / 2 * a * t * t
        current += x

        if 0.6 < current - distance < 1:
            x = x - 0.53
            tracks.append(round(x, 2))

        elif 1 < current - distance < 1.5:
            x = x - 1.4
            tracks.append(round(x, 2))
        elif 1.5 < current - distance < 3:
            x = x - 1.8
            tracks.append(round(x, 2))

        else:
            tracks.append(round(x, 2))

    print(sum(tracks))
    return tracks

第一次发文,希望各位大佬多多指正,如果需要源码或者模型定制尽管私信我,感谢支持!!

---------------------------------------------------------分割线---------------------------------------------------------------

刚刚有兄弟后台私信,向我要源码和模型,我所幸直接粘在下面了,兄弟们需要自己拿就好,仅供交流学习!!

另外模型和配置文件我还不会在这里发,需要的话私信我就好了

# -*- coding:utf-8 -*-
from configparser import ConfigParser
import random
from selenium import webdriver
import time
import base64
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import requests


class CreateConfig:
    def __init__(self, wz):
        config = ConfigParser(interpolation=None)
        config.read('config.ini', encoding='utf-8')
        self.key = config.get('keys', wz)
        self.passwd = config.get('passwd', wz)
        self.key_send = config.get('XPATH', f'{wz}_key_send')
        self.passwd_send = config.get('XPATH', f'{wz}_passwd_send')
        self.login = config.get('XPATH', f'{wz}_login')
        self.hk = config.get('XPATH', f'{wz}_hk')
        self.url = config.get('URL', f'{wz}_url')
        self.ua = config.get('UA', 'ua')
        self.img = config.get('XPATH', f'{wz}_img')
        self.img_save_path = config.get('PATH', 'img_path')
        self.wz = wz
        self.title = config.get('TITLE', f'{wz}_title')


class BrowserLogin(CreateConfig):
    def __init__(self, wz):
        super().__init__(wz)
        self.options = Options()
        self.options.add_argument(self.ua)
        self.options.add_argument('disable-infobars')
        self.options.add_experimental_option("useAutomationExtension", False)
        self.browser = webdriver.Chrome(options=self.options)

    def browser_login(self):
        time.sleep(1)
        return self.browser.find_element(By.XPATH, self.hk), self.browser.find_element(By.XPATH,
                                                                                       self.img).get_attribute('src')

    def detect(self, img_url):
        if self.wz == 'JD':
            image_base64 = img_url[22:]
            img_data = base64.b64decode(image_base64)
        elif self.wz == 'ZH':
            img_data = requests.get(img_url).content
        with open(self.img_save_path, 'wb') as f:
            f.write(img_data)
        data = {
            'image': open(self.img_save_path, 'rb')
        }
        data = requests.post('http://127.0.0.1:5000/upload', files=data)
        if self.wz == 'JD':
            return data.json().get('result').get('xmin') * 0.82
        else:
            return data.json().get('result').get('xmax')

    def get_track(self, distance):
        """
        根据偏移量和手动操作模拟计算移动轨迹
        :param distance: 偏移量
        :return: 移动轨迹
        """
        # 移动轨迹
        tracks = []
        # 当前位移
        current = 0
        # 减速阈值
        mid = distance * 4 / 5
        # 时间间隔
        t = 0.2
        # 初始速度
        v = 0

        while current < distance:
            if current < mid:
                a = random.uniform(2, 5)
            else:
                a = -(random.uniform(12.5, 13.5))
            v0 = v
            v = v0 + a * t
            x = v0 * t + 1 / 2 * a * t * t
            current += x

            if 0.6 < current - distance < 1:
                x = x - 0.53
                tracks.append(round(x, 2))

            elif 1 < current - distance < 1.5:
                x = x - 1.4
                tracks.append(round(x, 2))
            elif 1.5 < current - distance < 3:
                x = x - 1.8
                tracks.append(round(x, 2))

            else:
                tracks.append(round(x, 2))

        print(sum(tracks))
        return tracks

    def move_to_gap(self, slider, tracks):  # slider是要移动的滑块,tracks是要传入的移动轨迹
        ActionChains(self.browser).click_and_hold(slider).perform()
        for track in tracks:
            ActionChains(self.browser).move_by_offset(xoffset=track, yoffset=0).perform()
        time.sleep(0.18)
        # 反向滑动
        ActionChains(self.browser).move_by_offset(xoffset=-3, yoffset=0).perform()
        ActionChains(self.browser).move_by_offset(xoffset=3, yoffset=0).perform()
        time.sleep(0.7)
        ActionChains(self.browser).release().perform()

    def run(self):
        """
        :return:
        """
        self.browser.get(self.url)
        time.sleep(0.5)
        self.browser.refresh()
        time.sleep(0.7)
        self.browser.find_element(By.XPATH, self.key_send).send_keys(self.key)
        self.browser.find_element(By.XPATH, self.passwd_send).send_keys(self.passwd)
        time.sleep(0.8)
        self.browser.find_element(By.XPATH, self.login).click()
        time.sleep(1)
        while True:
            title = self.browser.title
            if title != self.title:
                break
            else:
                hk, img_url = self.browser_login()
                detect_value = self.detect(img_url)
                self.move_to_gap(hk, self.get_track(int(detect_value)))
                time.sleep(2)


if __name__ == '__main__':
    bro = BrowserLogin('JD')
    bro.run()

### Python 实现京东旋转对齐滑块验证码解决方案 对于京东网站上的旋转对齐类型的滑块验证码,处理方式相较于传统的直线滑动有所区别。这类验证码不仅需要识别出目标图案与背景之间的相对位移,还需要计算两者之间可能存在的角度偏差。 #### 图像预处理阶段 为了提高后续操作的成功率,在正式开始之前需先做必要的图像预处理工作。这一步骤涉及到了OpenCV库的应用,用于加载并调整待分析的图片质量以便更好地检测特征点。 ```python import cv2 from PIL import Image def preprocess_image(image_path): image = cv2.imread(image_path) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 转灰度图减少干扰因素 blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 高斯模糊进一步降低噪声影响 _, binary = cv2.threshold(blurred, 170, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU) return binary ``` #### 特征匹配与角度校正 通过模板匹配的方式找出拼图碎片的具体位置以及相对于完整图形的角度偏转情况。此过程依赖于SIFT/SURF等算法来提取关键点,并基于这些信息推算出正确的旋转量。 ```python import numpy as np def find_rotation_angle(template_img, target_img): sift = cv2.SIFT_create() kp1, des1 = sift.detectAndCompute(preprocess_image(template_img), None) kp2, des2 = sift.detectAndCompute(preprocess_image(target_img), None) bf = cv2.BFMatcher() matches = bf.knnMatch(des1,des2,k=2) good_points = [] for m,n in matches: if m.distance < 0.7*n.distance: good_points.append(m) src_pts = np.float32([kp1[m.queryIdx].pt for m in good_points]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_points]).reshape(-1, 1, 2) M, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) angle = np.arctan2(M[1][0], M[0][0]) * 180 / np.pi return abs(angle) ``` #### Selenium自动化交互流程 一旦获得了准确的目标坐标及所需转动的角度之后,则可通过Selenium驱动浏览器完成实际的操作动作。这里需要注意的是模拟人类真实的行为习惯,比如加入随机延迟时间使得整个过程更加自然流畅[^4]。 ```python from selenium.webdriver.common.action_chains import ActionChains import random import time def perform_slide_action(driver, slider_element, distance, rotation_angle): actions = ActionChains(driver) actions.click_and_hold(slider_element).pause(random.uniform(0.5, 1)).perform() steps = [(distance/10)*i for i in range(1, 11)] # 将总距离分为十个阶段逐步前进 angles = [rotation_angle*(j/9)-rotation_angle*0.5 for j in range(10)] # 计算每步应增加的角度变化幅度 for step, angle in zip(steps, angles): move_x = int(step*np.cos(np.radians(angle))) move_y = int(step*np.sin(np.radians(angle))) actions.move_by_offset(move_x, move_y).pause(random.uniform(0.1, 0.3)).perform() actions.release().perform() ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值