滑动验证码解决方案

Posted foryouos

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了滑动验证码解决方案相关的知识,希望对你有一定的参考价值。


滑动验证--中国保温网联系


# 两张图片,一张无缺口,一张有缺口,通过对比两张图片的像素点,找到缺口的位置(x)
# 获取两张图片
#获取坐标
# 模拟滑动,单一机器滑动,会以为
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains #滑动动作
from PIL import Image # 处理图片
from io import BytesIO
import re # 使用正则获取style的url
import requests # 获取url的图片信息
import time
import random # 使用随机函数进行设置速度

# 保存图片
def get_imge(driver,div_class,name):
    bg_imgs = driver.find_elements_by_class_name(div_class)
    #img_url =''
    location_list =[]
    for imge in bg_imgs:
        #print(imge.get_attribute("style")) # 获得图片style信息
        location = {}
        image_url = re.findall(r'background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;',
                               imge.get_attribute("style"))[0][0]
        location['x'] = re.findall(r'background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;',
                             imge.get_attribute("style"))[0][1]
        location['y'] = re.findall(r'background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;',
                             imge.get_attribute("style"))[0][2]
        #print(image_url,location['x'],location['y']) #获取上面检索的url,坐标
        location_list.append(location)
    response = requests.get(image_url).content
    image_content =BytesIO(response) # 像文件一样读取二进制文件

    #image.show()
    image = get_meige_image(image_content,location_list,name)
    image.save("{}.jpg".format(name))
    return image
# 获得像素点
def get_meige_image(image_content,location_list,name):
    #拼接图片
    image = Image.open(image_content)
    image_list_up =[]
    image_list_down =[]
    for location in location_list:
        if int(location['y']) ==-58:
            image_list_up.append(image.crop((abs(int(location['x'])),58,abs(int(location['x']))+10,116)))
        if int(location['y']) ==0:
            image_list_down.append(image.crop((abs(int(location['x'])),0,abs(int(location['x']))+10,58)))
    new_image = Image.new('RGB',(260,116))
    postion_x= 0
    for image in image_list_up:
        new_image.paste(image,(postion_x,0))
        postion_x +=10
    postion_x = 0
    for image in image_list_down:
        new_image.paste(image, (postion_x, 58))
        postion_x += 10
    #new_image.show() # 获取两张图片
    return new_image
#返回不同的x点
def get_diff_location(image1,image2):
    '''
    通过对比图像找到缺口位置
    :param image1:
    :param image2:
    :return:
    '''

    for y in range(1, 115):
        for x in range(1,259):

            # 判断成立,表示这个点,两张图的像素点
            if is_similar(image1,image2,x,y) == False:
                return x

# 获取不相同点
def is_similar(image1,image2,x,y):
    pixel1 = image1.getpixel((x,y))
    pixel2 = image2.getpixel((x,y)) # 元组
    for i in range(0,3):
        if (abs(pixel1[i] - pixel2[i]) >= 50):
            return False
    return True

# 模拟滑动,使网站难以识别是认为运动
def get_take(x):
    '''
    模拟匀加速后匀减速运动,加上来回滑动
    :param x:
    :return:
    '''

    v = 0#初速度
    t = 1
    temp =0
    tracks=[]
    mid = x*5 / 8
    x = x + 10

    while temp < x:
        if temp < mid :
            a =random.randint(1,3)
        else:
            a = -random.randint(2,4)
        v0 = v
        s = v0 * t + (1/2)* a * (t ** 2)
        tracks.append(round(s))
        temp += s
        v = v0 + a*t
    for i in range(4):
        tracks.append(-random.randint(6,10)) # 此数字可以有变化进行调整,根据规则,当网站识别你为机器人时,它会使误差增大,从而失败,尽量不要使网站识别出来
    return tracks
def main(driver,elem):

    image1= get_imge(driver,'gt_cut_fullbg_slice','fullbg')
    image2 = get_imge(driver, 'gt_cut_bg_slice','bg')

    x = get_diff_location(image1,image2)
    print("应该移动的坐标:{}".format(x)) #输出滑到的x点
    # 最基本的滑动轨迹,会检验出来是电脑自动滑的,怪物已经吃了拼图
    ActionChains(driver).click_and_hold(elem).perform()
    #模拟匀加速运动
    tracks = get_take(x)
    for x1 in tracks:
        ActionChains(driver).move_by_offset(xoffset=x1,yoffset=0).perform()
    #ActionChains(driver).move_by_offset(xoffset=-20,yoffset=0).perform() #进行局部调整进行对准
    ActionChains(driver).release(elem).perform()
    time.sleep(1)


if __name__ == "__main__":
    driver = webdriver.Chrome()
    # 获得url
    driver.get("http://www.cnbaowen.net/api/geetest/")
    try:
        count=5
        # 时间缓冲
        wait = WebDriverWait(driver, 10)
        # 定位到滑块
        elem = wait.until(EC.element_to_be_clickable((By.CLASS_NAME, "gt_slider_knob")))
        while count > 0:
            main(driver,elem)
            try:
                success = wait.until(EC.visibility_of((By.XPATH,"//div[@class='gt_slider']/div[@class='gt_ajax_tip gt_success'])")))
                if success:
                    print("success")
                    break
            except Exception as e:
                print("error")
                time.sleep(1)
    finally:
        driver.quit()


以B站登陆为例子


from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains #滑动动作
from PIL import Image # 处理图片
from io import BytesIO
import re # 使用正则获取style的url
import requests # 获取url的图片信息
import time
import random # 使用随机函数进行设置速度

#账号密码输入
def login(user,passwd):
    username =wait.until(EC.presence_of_element_located((By.ID,"login-username")))
    username.send_keys(user)
    password =wait.until(EC.presence_of_element_located((By.ID,"login-passwd")))
    password.send_keys(passwd)
    time.sleep(2)
    #双击登录
    element =driver.find_element_by_xpath("//a[@class='btn btn-login']")
    ActionChains(driver).double_click(element).perform()
    #设置延时
    time.sleep(3)
def get_image():
    geetest =wait.until(EC.presence_of_element_located((By.XPATH,"//canvas[@class='geetest_canvas_slice geetest_absolute']")))
    geetest.screenshot("bg.png")
    image_bg = Image.open("bg.png")
    js = 'var change = document.getElementsByClassName("geetest_canvas_fullbg"); change[0].style = "display: block;"'
    driver.execute_script(js)
    time.sleep(2)
    geetest_canvas_fullbg = wait.until(EC.presence_of_element_located((By.CLASS_NAME,"geetest_canvas_fullbg ")))
    geetest_canvas_fullbg.screenshot("fullbg.png")
    image_fullbg = Image.open("fullbg.png")
    return image_bg,image_fullbg
#返回不同的x点
def get_diff_location(image1,image2):
    '''
    通过对比图像找到缺口位置
    :param image1:
    :param image2:
    :return:
    '''

    for x in range(60, image1.size[0]):
        for y in range(1,image1.size[1]):

            # 判断成立,表示这个点,两张图的像素点
            if is_similar(image1,image2,x,y) == False:
                return x

# 获取不相同点
def is_similar(image1,image2,x,y):
    pixel1 = image1.getpixel((x,y))
    pixel2 = image2.getpixel((x,y)) # 元组
    for i in range(0,3):
        if (abs(pixel1[i] - pixel2[i]) >= 50):
            return False
    return True

# 模拟滑动,使网站难以识别是认为运动
def get_take(x):
    '''
    模拟匀加速后匀减速运动,加上来回滑动
    :param x:
    :return:
    '''

    v = 0#初速度
    t = 1
    temp =0
    tracks=[]
    mid = x*5 / 8
    x = x + 10

    while temp < x:
        if temp < mid :
            a =random.randint(1,3)
        else:
            a = -random.randint(2,4)
        v0 = v
        s = v0 * t + (1/2)* a * (t ** 2)
        tracks.append(round(s))
        temp += s
        v = v0 + a*t
    for i in range(4):
        tracks.append(-random.randint(2,4)) # 此数字可以有变化进行调整,根据规则,当网站识别你为机器人时,它会使误差增大,从而失败,尽量不要使网站识别出来
    return tracks
def main(driver,elem):
    image_bg,image_fullbg = get_image()
    x = get_diff_location(image_bg,image_fullbg)
    #print("应该移动的坐标:{}".format(x)) #输出滑到的x点
    # 最基本的滑动轨迹,会检验出来是电脑自动滑的,怪物已经吃了拼图
    ActionChains(driver).click_and_hold(elem).perform()
    #模拟匀加速运动
    tracks = get_take(x-7) #获取滑块的初始位置,要减去
    for x1 in tracks:
        ActionChains(driver).move_by_offset(xoffset=x1,yoffset=0).perform()
    #ActionChains(driver).move_by_offset(xoffset=-20,yoffset=0).perform() #进行局部调整进行对准
    ActionChains(driver).release(elem).perform()
    time.sleep(1)
    try:
        driver.find_element_by_class_name("1111")
    except:
        driver.refresh()
        main()
if __name__ == '__main__':
    driver = webdriver.Chrome()
    driver.get("https://passport.bilibili.com/login")
    wait = WebDriverWait(driver, 10)
    login("xxxxxxxxxxx","xxxxxxxxx")
    elem = wait.until(EC.presence_of_element_located((By.CLASS_NAME,"geetest_slider_button")))
    main(driver,elem)



以上是关于滑动验证码解决方案的主要内容,如果未能解决你的问题,请参考以下文章

七步完美解决问题python爬虫极验滑动验证码问题

python_selenium简单的滑动验证码

不写代码,如何用深度学习自动识别滑动验证码缺口位置?

app中阿里云滑动验证码和抓取代码解耦的一些尝试

app中阿里云滑动验证码和抓取代码解耦的一些尝试

python验证码识别极验滑动验证码识别