posts - 32,  comments - 0,  views - 13464
复制代码
#!/user/bin/python3
# -*- coding:utf-8 -*-
# @Author: zhaoruixiao
# @Datetime: 2023/4/21 14:15
# @Software: PyCharm
# @File    : test.py
"""
    work for $ 
"""
import time
from PIL import Image
from selenium import webdriver
import random
from selenium.webdriver.common.by import By
# from shu import *  # 我自己导的要输入的账号密码包
from selenium.webdriver import ActionChains


# 一、获取图片
def get_captcha():
    '''取得验证码的图片'''
    time.sleep(2)
    # 1、隐藏滑块,得到缺口图
    js_hide_slice = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="none"'
    driver.execute_script(js_hide_slice)
    # 截取缺口图
    part_imgpath = './part.png'
    driver.find_element_by_class_name("geetest_canvas_bg").screenshot(part_imgpath)
    # 2、隐藏缺口图 ,得到滑块图
    js_show_slice = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="block"'
    js_hide_part = 'document.getElementsByClassName("geetest_canvas_bg")[0].style.display="none"'
    driver.execute_script(js_show_slice + ";" + js_hide_part)
    # 截取滑块图
    slice_imgpath = './slice.png'
    driver.find_element_by_class_name("geetest_canvas_slice").screenshot(slice_imgpath)
    # 3、显示完整图 geetest_canvas_fullbg
    js_show_full1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="1"'
    js_show_full2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"'
    driver.execute_script(js_show_full1 + ";" + js_show_full2)
    # 截取完整图形
    full_imgpath = './full.png'
    driver.find_element_by_class_name("geetest_canvas_fullbg").screenshot(full_imgpath)
    # 还原
    js_hide_full1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none"'
    js_hide_full2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="0"'
    js_show_part = 'document.getElementsByClassName("geetest_canvas_bg")[0].style.display=""'
    driver.execute_script(js_hide_full1 + ";" + js_hide_full2 + ";" + js_show_part)

    return slice_imgpath, part_imgpath, full_imgpath


# 二、计算距离
def get_slice_X(slice_imgpath):
    '''获取滑块左边缘X'''
    img = Image.open(slice_imgpath)
    w, h = img.size
    for i in range(w):
        for j in range(h):
            rgb = img.getpixel((i, j))
            print((i, j), rgb)
            if rgb[0] + rgb[1] + rgb[2] < 250:
                return (i, j), rgb


def get_gap_X(part_imgpath, full_imgpath):
    '''获取缺口左边缘x坐标'''
    part_img = Image.open(part_imgpath)
    full_img = Image.open(full_imgpath)
    w, h = part_img.size
    for i in range(w):
        for j in range(h):
            part_point = part_img.getpixel((i, j))
            full_point = full_img.getpixel((i, j))
            # 比较缺口图与完整图,相同坐标点,颜色差,缺口位置色差比较大
            r = part_point[0] - full_point[0]
            g = part_point[1] - full_point[1]
            b = part_point[2] - full_point[2]
            abs_value = abs(r) + abs(g) + abs(b)
            if abs_value > 110:
                return i, j


def get_distance(slice_imgpath, part_imgpath, full_imgpath):
    slice_X = get_slice_X(slice_imgpath)[0][0]
    gap_X = get_gap_X(full_imgpath, part_imgpath)[0]
    distance = gap_X - slice_X
    return distance


# 三、模拟人工移动
def get_track(distance):
    # 初速度
    v = 0
    # 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
    t = 0.2
    # 位移/轨迹列表、列表内的一个元素代表0.2s的位移
    tracks = []
    # 当前的位移
    current = 0
    # 到达mid值开始减速
    mid = distance * 5 / 8
    distance += 10  # 先滑过一点,最后再反着滑动回来
    while current < distance:
        t = random.randint(1, 4) / 10  # 将时间设为随机,更符合人的行为
        if current < mid:
            # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
            a = random.randint(1, 3)  # 加速运动
        else:
            a = random.randint(2, 4)  # 减速运动
        # 初速度
        v0 = v
        # t秒时间内的位移
        s = v0 * t + 0.5 * a * (t ** 2)
        # 当前的位置
        current += s
        # 添加到轨迹列表
        tracks.append(round(s))
        # 速度已经达到v,该速度作为下次的初速度
        v = v0 + a * t
    # 反着滑动到大概准确位置
    temp = 10 + round(current - distance)  # 比原来正确的位置多了的像素
    for i in range(5):
        num = -random.randint(1, 3)
        tracks.append(num)
        temp += num
    # 位移的补偿
    tracks.append(abs(temp)) if temp < 0 else tracks.append(-temp)
    # random.shuffle(tracks)
    print(tracks)
    return tracks


# selenium操作
# 移动滑块
def move_slider(tracks):
    element = driver.find_element_by_class_name("geetest_slider_button")
    ActionChains(driver).click_and_hold(element).perform()
    for x in tracks:
        ActionChains(driver).move_by_offset(xoffset=x, yoffset=0).perform()
    ActionChains(driver).release(element).perform()
    time.sleep(2)


if __name__ == '__main__':

    driver = webdriver.Chrome()
    driver.implicitly_wait(10)
    # 登录网址
    driver.get('https://account.zbj.com/login')
    driver.maximize_window()
    # 点击验证
    driver.find_element_by_xpath('//*[@id="utopia_widget_10"]/ul/ol/a/span/img').click()
    driver.find_element_by_class_name("geetest_radar_tip_content").click()
    time.sleep(1)
    # 账号和密码
    name = driver.find_element(By.NAME, 'username').send_keys("USER")
    password = driver.find_element(By.NAME, 'password').send_keys("PASSWORD")
    time.sleep(2)
    # 获取缺口图,滑块图,完整图
    part_imgpath, slice_imgpath, full_imgpath = get_captcha()

    # 获取距离
    distance = get_distance(part_imgpath, slice_imgpath, full_imgpath)
    print(distance)

    count = 6
    while count > 0:
        # 获取轨迹
        tracks = get_track(distance)
        # selenium操作
        move_slider(tracks)
        success = driver.find_element_by_class_name("geetest_success_radar_tip_content").text
        if success:
            print("校验成功", success)
            time.sleep(1)
            driver.find_element_by_class_name("zbj-btn-primary").click()
            break
        else:
            count += 1
        # 出现被怪兽吃掉,网络不给力
        info_tag = driver.find_element_by_class_name("geetest_reset_tip_content")
        internet_info = info_tag.text
        if "点击重试" in internet_info:
            info_tag.click()
            # 获取缺口图,滑块图,完整图
            part_imgpath, slice_imgpath, full_imgpath = get_captcha()
            # 获取距离
            distance = get_distance(part_imgpath, slice_imgpath, full_imgpath)
            print(distance)

    # element = driver.find_element_by_class_name("geetest_slider_button")
    # ActionChains(driver).click_and_hold(element).perform()
    # ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
    # ActionChains(driver).release(element).perform()
    time.sleep(10)

    # driver.close()
复制代码

一、登录网址跳转到滑块验证码界面

登录网址:
url=https://account.zbj.com/login

先拿到这个标签,在跳转到滑块验证码界面。

    from selenium import webdriver
     
    driver=webdriver.Chrome()
    driver.implicitly_wait(10)
     
    #登录网址
    driver.get('https://account.zbj.com/login')
    driver.maximize_window()
    #点击验证
    driver.find_element_by_xpath('//*[@id="utopia_widget_10"]/ul/ol/a/span/img').click()
    driver.find_element_by_class_name("geetest_radar_tip").click()

跳转出的结果图:

 二、验证码图片的处理

验证码图片有缺口图、滑块图、完整图,三张构成。

逻辑思想:1.让滑块隐藏,截取缺口图;

                  2.隐藏缺口图,显示滑块图,截取滑块图;

                  3.显示完整图,截取完整图。

    import time
    from selenium import webdriver
     
    def get_captcha():
        '''取得验证码的图片'''
        time.sleep(2)
        #1、隐藏滑块,得到缺口图
        js_hide_slice = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="none"'
        driver.execute_script(js_hide_slice)
        #截取缺口图
        part_imgpath='./part.png'
        driver.find_element_by_class_name("geetest_canvas_bg").screenshot(part_imgpath)
        #2、隐藏缺口图 ,得到滑块图
        js_show_slice='document.getElementsByClassName("geetest_canvas_slice")[0].style.display="block"'
        js_hide_part='document.getElementsByClassName("geetest_canvas_bg")[0].style.display="none"'
        driver.execute_script(js_show_slice+";"+js_hide_part)
        #截取滑块图
        slice_imgpath='./slice.png'
        driver.find_element_by_class_name("geetest_canvas_slice").screenshot(slice_imgpath)
        #3、显示完整图 geetest_canvas_fullbg
        js_show_full1='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="1"'
        js_show_full2='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"'
        driver.execute_script(js_show_full1+";"+js_show_full2)
        #截取完整图形
        full_imgpath='./full.png'
        driver.find_element_by_class_name("geetest_canvas_fullbg").screenshot(full_imgpath)
        #还原
        js_hide_full1='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="0"'
        js_hide_full2='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none"'
        js_show_part='document.getElementsByClassName("geetest_canvas_bg")[0].style.display=""'
        driver.execute_script(js_hide_full1+";"+js_hide_full2+";"+js_show_part)
     
        return part_imgpath,slice_imgpath,full_imgpath
     
    if __name__ == '__main__':
     
        driver=webdriver.Chrome()
        driver.implicitly_wait(10)
        #登录网址
        driver.get('https://account.zbj.com/login')
        driver.maximize_window()
        #点击验证
        driver.find_element_by_xpath('//*[@id="utopia_widget_10"]/ul/ol/a/span/img').click()
        driver.find_element_by_class_name("geetest_radar_tip").click()
        time.sleep(1)
        # 获取缺口图,滑块图,完整图
        part_imgpath, slice_imgpath, full_imgpath = get_captcha()

取到了三张图片:

三、计算距离

逻辑思想:

    #逻辑思路
    def get_slice_X():
     '''获取滑块左边缘X'''
        pass
     
     
     def get_gap_X():
        '''获取缺口左边缘x坐标'''
        pass
     
    def get_distance():
        '''计算距离'''
        pass

接下来对获取的滑块左边缘X进行编写与测试取值:建一个py文件,将下面代码放入,运行。

    from PIL import Image
    part_imgpath='./part.png'
    slice_imgpath='./slice.png'
    full_imgpath = './full.png'
    def get_slice_X(slice_imgpath):
        '''获取滑块左边缘X'''
        img=Image.open(slice_imgpath)
        w,h=img.size
        for i in range(w):
            for j in range(h):
                rgb=img.getpixel((i,j))
                print((i,j),rgb)
                if rgb[0]+rgb[1]+rgb[2]<250:
                    return (i,j),rgb
    data=get_slice_X(slice_imgpath)
    print(data)

运行结果:

 对获取缺口左边缘X坐标进行编写和测试:建立.py文件放入代码

    from PIL import Image
    part_imgpath='./part.png'
    slice_imgpath='./slice.png'
    full_imgpath = './full.png'
     
     
    def get_gap_X(part_imgpath,full_imgpath):
        '''获取缺口左边缘x坐标'''
        part_img = Image.open(part_imgpath)
        full_img = Image.open(full_imgpath)
        w, h = part_img.size
        for i in range(w):
            for j in range(h):
                part_point = part_img.getpixel((i, j))
                full_point = full_img.getpixel((i, j))
                #比较缺口图与完整图,相同坐标点,颜色差,缺口位置色差比较大
                r = part_point[0] - full_point[0]
                g = part_point[1] - full_point[1]
                b = part_point[2] - full_point[2]
                abs_value = abs(r) + abs(g) + abs(b)
                if abs_value>120:
                    return i,j
                print("abs_value",(r,g,b),abs_value,(i,j))
    data=get_gap_X(part_imgpath,full_imgpath)
    print(data)

运行结果:

 计算距离:

    def get_distance(slice_imgpath,part_imgpath,full_imgpath):
        slice_X = get_slice_X(slice_imgpath)[0][0]
        gap_X = get_gap_X(full_imgpath, part_imgpath)[0]
        distance = gap_X - slice_X
        return distance

四、模拟人工运动

1、直接根据获取到的距离移动,滑块与缺口能够契合但是不能通过

2、牛顿运动定律模拟人工移动,偶尔有通过,概率低。

3、增加随机性模拟人工移动轨迹,通过概率高。

五、移动滑块

    def move_slider(tracks):
        element=driver.find_element_by_class_name("geetest_slider_button")
        ActionChains(driver).click_and_hold(element).perform()
        for x in tracks:
            ActionChains(driver).move_by_offset(xoffset=x,yoffset=0).perform()
        ActionChains(driver).release(element).perform()
        time.sleep(2)

完整代码:

    import time
    from PIL import Image
    from selenium import webdriver
    import random
    from selenium.webdriver.common.by import By
    from shu import *            #我自己导的要输入的账号密码包
    from selenium.webdriver import ActionChains
     
    #一、获取图片
    def get_captcha():
        '''取得验证码的图片'''
        time.sleep(2)
        #1、隐藏滑块,得到缺口图
        js_hide_slice = 'document.getElementsByClassName("geetest_canvas_slice")[0].style.display="none"'
        driver.execute_script(js_hide_slice)
        #截取缺口图
        part_imgpath='./part.png'
        driver.find_element_by_class_name("geetest_canvas_bg").screenshot(part_imgpath)
        #2、隐藏缺口图 ,得到滑块图
        js_show_slice='document.getElementsByClassName("geetest_canvas_slice")[0].style.display="block"'
        js_hide_part='document.getElementsByClassName("geetest_canvas_bg")[0].style.display="none"'
        driver.execute_script(js_show_slice+";"+js_hide_part)
        #截取滑块图
        slice_imgpath='./slice.png'
        driver.find_element_by_class_name("geetest_canvas_slice").screenshot(slice_imgpath)
        #3、显示完整图 geetest_canvas_fullbg
        js_show_full1='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="1"'
        js_show_full2='document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="block"'
        driver.execute_script(js_show_full1+";"+js_show_full2)
        #截取完整图形
        full_imgpath='./full.png'
        driver.find_element_by_class_name("geetest_canvas_fullbg").screenshot(full_imgpath)
        #还原
        js_hide_full1 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.display="none"'
        js_hide_full2 = 'document.getElementsByClassName("geetest_canvas_fullbg")[0].style.opacity="0"'
        js_show_part='document.getElementsByClassName("geetest_canvas_bg")[0].style.display=""'
        driver.execute_script(js_hide_full1+";"+js_hide_full2+";"+js_show_part)
     
        return slice_imgpath,part_imgpath,full_imgpath
    #二、计算距离
    def get_slice_X(slice_imgpath):
        '''获取滑块左边缘X'''
        img = Image.open(slice_imgpath)
        w, h = img.size
        for i in range(w):
            for j in range(h):
                rgb = img.getpixel((i, j))
                print((i, j), rgb)
                if rgb[0] + rgb[1] + rgb[2] < 250:
                    return (i, j), rgb
    def get_gap_X(part_imgpath,full_imgpath):
        '''获取缺口左边缘x坐标'''
        part_img = Image.open(part_imgpath)
        full_img = Image.open(full_imgpath)
        w, h = part_img.size
        for i in range(w):
            for j in range(h):
                part_point = part_img.getpixel((i, j))
                full_point = full_img.getpixel((i, j))
                #比较缺口图与完整图,相同坐标点,颜色差,缺口位置色差比较大
                r = part_point[0] - full_point[0]
                g = part_point[1] - full_point[1]
                b = part_point[2] - full_point[2]
                abs_value = abs(r) + abs(g) + abs(b)
                if abs_value>110:
                    return i,j
     
    def get_distance(slice_imgpath,part_imgpath,full_imgpath):
        slice_X = get_slice_X(slice_imgpath)[0][0]
        gap_X = get_gap_X(full_imgpath, part_imgpath)[0]
        distance = gap_X - slice_X
        return distance
     
    #三、模拟人工移动
    def get_track(distance):
        #初速度
        v=0
        #单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
        t=0.2
        # 位移/轨迹列表、列表内的一个元素代表0.2s的位移
        tracks = []
        #当前的位移
        current=0
        #到达mid值开始减速
        mid=distance*5/8
        distance+=10    #先滑过一点,最后再反着滑动回来
        while current<distance:
            t=random.randint(1,4)/10    #将时间设为随机,更符合人的行为
            if current<mid:
                #加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
                a=random.randint(1,3)#加速运动
            else:
                a=random.randint(2,4)#减速运动
            #初速度
            v0=v
            #t秒时间内的位移
            s=v0*t+0.5*a*(t**2)
            #当前的位置
            current+=s
            #添加到轨迹列表
            tracks.append(round(s))
            #速度已经达到v,该速度作为下次的初速度
            v=v0+a*t
        #反着滑动到大概准确位置
        temp=10+round(current-distance)#比原来正确的位置多了的像素
        for i in range(5):
            num=-random.randint(1,3)
            tracks.append(num)
            temp+=num
        #位移的补偿
        tracks.append(abs(temp))if temp<0 else tracks.append(-temp)
        # random.shuffle(tracks)
        print(tracks)
        return tracks
    # selenium操作
    #移动滑块
    def move_slider(tracks):
        element=driver.find_element_by_class_name("geetest_slider_button")
        ActionChains(driver).click_and_hold(element).perform()
        for x in tracks:
            ActionChains(driver).move_by_offset(xoffset=x,yoffset=0).perform()
        ActionChains(driver).release(element).perform()
        time.sleep(2)
     
     
    if __name__ == '__main__':
     
        driver=webdriver.Chrome()
        driver.implicitly_wait(10)
        #登录网址
        driver.get('https://account.zbj.com/login')
        driver.maximize_window()
        #点击验证
        driver.find_element_by_xpath('//*[@id="utopia_widget_10"]/ul/ol/a/span/img').click()
        driver.find_element_by_class_name("geetest_radar_tip_content").click()
        time.sleep(1)
        #账号和密码
        name = driver.find_element(By.NAME, 'username').send_keys(USER)
        password = driver.find_element(By.NAME, 'password').send_keys(PASSWORD)
        time.sleep(2)
        # 获取缺口图,滑块图,完整图
        part_imgpath, slice_imgpath, full_imgpath = get_captcha()
     
        # 获取距离
        distance = get_distance(part_imgpath, slice_imgpath, full_imgpath)
        print(distance)
     
     
        count=6
        while count>0:
            # 获取轨迹
            tracks = get_track(distance)
            # selenium操作
            move_slider(tracks)
            success=driver.find_element_by_class_name("geetest_success_radar_tip_content").text
            if success:
                print("校验成功",success)
                time.sleep(1)
                driver.find_element_by_class_name("zbj-btn-primary").click()
                break
            else:
                count+=1
            #出现被怪兽吃掉,网络不给力
            info_tag=driver.find_element_by_class_name("geetest_reset_tip_content")
            internet_info=info_tag.text
            if "点击重试" in internet_info:
                info_tag.click()
                # 获取缺口图,滑块图,完整图
                part_imgpath, slice_imgpath, full_imgpath = get_captcha()
                # 获取距离
                distance = get_distance(part_imgpath, slice_imgpath, full_imgpath)
                print(distance)
     
     
        # element = driver.find_element_by_class_name("geetest_slider_button")
        # ActionChains(driver).click_and_hold(element).perform()
        # ActionChains(driver).move_by_offset(xoffset=distance, yoffset=0).perform()
        # ActionChains(driver).release(element).perform()
        time.sleep(10)
     
        # driver.close()

账号与密码的py文件

    USER='xxxxx'            #你自己注册的账号
    PASSWORD='xxxxx'         #密码

最后要说的是,在 49行的取的250这个值是个大概范围值,可能要多运行几次才能成功,但逻辑,代码还行吧。

def get_slice_X(slice_imgpath):
    '''获取滑块左边缘X'''

posted on   aha_baby  阅读(60)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示