selenium的滑块验证码的模拟登录(猪八戒网站)

(17) 2024-04-23 08:01:01

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

登录网址:

url=https://account.zbj.com/login

selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第1张

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

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()

跳转出的结果图:

selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第2张

 二、验证码图片的处理

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

selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第3张

逻辑思想: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()

取到了三张图片:

selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第4张

三、计算距离

逻辑思想:

#逻辑思路
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)

运行结果:selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第5张 

 对获取缺口左边缘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)

运行结果:selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第6张 

 计算距离:

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'''

好多步骤都省了,是直接上的代码,就参考学习吧。哈哈!selenium的滑块验证码的模拟登录(猪八戒网站) (https://mushiming.com/)  第7张

 

THE END

发表回复