博客园,模拟登陆破解滑动验证码

更新

多次测试,在计算像素误差时,改为40会更准确,因为有些图片会有淡阴影,导致获取距离时获取到淡阴影距离,而不是实际距离。 

在需要验证时,会正常弹出如下验证码,已经其属性:

 

 

更改上图标红的属性,获取新图片:

 

 新验证码和旧验证码有两处明显不同。

其一:可移动拼图

其二:需填充缺口

思路:

获取两个验证码的图片,比较两张验证码,获取像素不同的坐标距离x轴的距离,共两个值

两个值的差,就是拼图所要移动的距离。

模拟移动,测试数据即可。

import random
import time
from PIL import Image
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains


def isSimilar(image1, image2, x, y):
    """
    比较两种图片在(x,y)坐标点位置的像素值是否一样
    :param image1:
    :param image2:
    :param x:
    :param y:
    :return: True->一样
    """
    # 获取图片在x,y位置的像素值
    pixel1 = image1.getpixel((x, y))
    pixel2 = image2.getpixel((x, y))
    # 计算要考虑误差的影响
    if abs(pixel1[0] - pixel2[0]) >= 40 and abs(pixel1[1] - pixel2[1]) >= 40 and abs(pixel1[2] - pixel2[2]) >= 40:
        return False
    return True


def get_distance(image1, image2, x=None):
    """
    通过对比两张一样的图片,获取不一样点的坐标
    :param image1:
    :param image2:
    :param x
    :return: i
    """
    # 比较是比较每个坐标点的像素值
    # 这两种图片是一样大小的
    for i in range(x, 198):  # x轴
        for j in range(154):  # y轴
            # (i,j)--->图片上的每个坐标点
            if isSimilar(image1, image2, i, j) == False:
                return i


def get_tracks(distance):
    # 拖动超过拼接位置8个距离
    distance += 8
    v = 0
    t = 0.2
    tracks = []
    current = 0
    mid = distance * 7 / 8
    while current < distance:
        if current < mid:
            a = random.randint(2, 4)
        else:
            a = -random.randint(3, 5)
        v0 = v
        s = v0 * t + 0.5 * a * (t ** 2)
        current += s
        tracks.append(round(s))
        v = v0 + a * t
    # 补回超过距离为10,可多次测试,自测误差,进行多补或少补
    x = [-2, -3, -3, -2]
    tracks += x
    return tracks


def login_verify(driver):
    # 获取滑块
    slider = driver.find_element_by_class_name('geetest_slider_button')
    # 最大化浏览器
    driver.maximize_window()
    # 获取验证码所在位置
    yz_element = driver.find_element_by_css_selector('[class="geetest_canvas_img geetest_absolute"]')

    top = yz_element.location['y']
    left = yz_element.location['x']
    right = left + yz_element.size['width']
    bottom = top + yz_element.size['height']

    # 截图保存有缺口的图片完整图片
    driver.save_screenshot('quan_quekou.png')
    image_qk = Image.open('quan_quekou.png')
    # 根据在上面获取的验证码位置在截图中截取验证码图片
    image1 = image_qk.crop((left, top, right, bottom))
    image1.save('imaeg1.png')

    # 该canvas画布的属性:让其出现无缺的原图
    driver.execute_script('document.getElementsByClassName("geetest_canvas_fullbg")[0].style="display: block"')

    # 截图保存无缺口的图片完整图片
    driver.save_screenshot('quan_wuque.png')
    # 根据在上面获取的验证码位置在截图中截取验证码图片
    image2 = Image.open('quan_wuque.png').crop((left, top, right, bottom))
    image2.save('image2.png')

    # 比较两张验证码的内容,获取距离
    # x1:可移动拼图的左上角坐标距x轴的距离,
    # 在获取距离方法中传0,
    # 图片第一处不同是可移动拼图位置覆盖引起的图片像素不同,该不同在图片靠近x轴的地方
    x1 = int(get_distance(image1, image2, 0))

    # x2:图形缺口左上角坐标距x轴的距离,
    # 在获取距离方法中传60,
    # 图片第二处不同是在拼接处,稍远于x轴,在不同网站下,该值可能会有不同
    x2 = int(get_distance(image1, image2, 60))
    # 两距离的差即为拼图与缺口的真实距离
    # print(x1, x2)
    distance = abs(x1 - x2)

    # # 3、使用鼠标动作链进行点击并悬浮
    ActionChains(driver).click_and_hold(on_element=slider).perform()
    # 获取移动距离列表
    tracks = get_tracks(distance)
    # 开始移动,加速,减速,超过,拖回
    for x in tracks:
        ActionChains(driver).move_by_offset(xoffset=x, yoffset=random.randint(0, 2)).perform()
    time.sleep(1)
    ActionChains(driver).release(slider).perform()


if __name__ == '__main__':
    driver = webdriver.Chrome()
    driver.get('https://account.cnblogs.com/signin')
    # 隐式等待
    driver.implicitly_wait(20)
    # 输入用户名和密码
    driver.find_element_by_xpath('//*[@id="mat-input-0"]').send_keys('账号')
    driver.find_element_by_xpath('//*[@id="mat-input-1"]').send_keys('密码')
    # 点击登录按钮
    driver.find_element_by_xpath(
        '//*[@class="mat-focus-indicator action-button ng-tns-c141-2 mat-flat-button mat-button-base mat-primary"]').click()
    time.sleep(2)
    login_verify(driver)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值