python爬虫之验证码篇3-滑动验证码识别技术

yizhihongxing

Python爬虫之验证码篇3-滑动验证码识别技术

本篇文章将带领大家学习如何使用Python进行滑动验证码识别技术,让我们能够愉快地完成爬虫任务,无需被恼人的滑动验证码阻挡。

前置技能

在学习本篇文章之前,您需要学会以下技能:

  • Python基础知识
  • Python爬虫入门基础
  • 了解验证码的基本原理

滑动验证码介绍

滑动验证码通常由一张包含有缺口的图片以及一个滑块组成,用户需要拖动滑块,使其到达缺口位置,才能验证身份。滑动验证码用于防止机器自动注册和登录,增强网站的注册和登录安全性。

滑动验证码攻略

1. 识别缺口位置

滑动验证码的关键在于识别缺口的位置,这个缺口的位置是不能预测的,需要通过一定的方式来确定。

我们可以使用selenium来模拟用户操作,拖动滑块,记录滑动前后的页面截图,然后使用图像识别技术找到滑块的移动距离,进而得出缺口的位置。

以下是示例代码:

from selenium import webdriver
from selenium.webdriver import ActionChains
import time
from PIL import Image
import math

def get_snap(driver):
    '''
    获取网页截图
    '''
    driver.save_screenshot('snap.png')
    snap_obj = Image.open('snap.png')
    return snap_obj

def get_image(driver, element):
    '''
    获取指定元素的截图
    '''
    location = element.location
    size = element.size
    left = location['x']
    top = location['y']
    right = left + size['width']
    bottom = top + size['height']

    # 截取指定位置的窗口
    snap_obj = get_snap(driver)
    image_obj = snap_obj.crop((left, top, right, bottom))
    return image_obj

def get_distance(image1, image2):
    '''
    获取两张图片的距离
    '''
    threshold = 100
    rgb1 = image1.convert('RGB')
    rgb2 = image2.convert('RGB')
    diffs = 0
    for i in range(0, rgb1.size[0]):
        for j in range(0, rgb1.size[1]):
            r, g, b = rgb1.getpixel((i, j))
            r2, g2, b2 = rgb2.getpixel((i, j))
            diff = abs(r - r2) + abs(g - g2) + abs(b - b2)
            if diff > threshold:
                diffs += diff

    return diffs

def get_track(distance):
    '''
    根据距离获取轨迹滑动的路线
    '''
    track = []
    current = 0
    mid = distance * 4 / 5
    t = 0.2
    v = 0

    while current < distance:
        if current < mid:
            a = 2
        else:
            a = -3
        v0 = v
        v = v0 + a * t
        move = v0 * t + 0.5 * a * t * t
        current += int(move)
        track.append(current)

    # 计算轨迹的减速部分
    extra = int(distance * 1.05) - current
    for i in range(extra):
        current += 1
        track.append(current)

    return track

def get_slider(driver):
    '''
    获取滑块对象
    '''
    slider = driver.find_element_by_xpath('//div[@class="login-pwd-code-content"]/div[2]')
    return slider

# 实例化WebDriver
driver = webdriver.Chrome()

# 打开登录页面
driver.get('https://www.zhihu.com/signin')

# 输入账号密码
driver.find_element_by_name('username').send_keys('test')
driver.find_element_by_name('password').send_keys('test123')

# 识别滑块位置
slider = get_slider(driver)
slider_img = get_image(driver, slider)
slider.click()

# 模拟滑块拖动
action = ActionChains(driver)
action.click_and_hold(slider).perform()

# 通过不断试验推算拖动位移
distance = 0
while distance == 0:
    action.move_by_offset(10, 0).perform()
    current_img = get_image(driver, slider)
    distance = get_distance(slider_img, current_img)
print('缺口位置距离', distance)        

track = get_track(distance)
for x in track:
    action.move_by_offset(x, 0).perform()

# 释放滑块,完成登录
action.release().perform()

2. 使用机器学习模型识别滑块验证码

除了使用图像识别技术识别滑块验证码,我们还可以使用机器学习模型进行识别。我们可以将滑块验证码的每一个位置看成一个像素点,并标记其是否为缺口(1为缺口,0为非缺口),然后训练机器学习模型进行识别。

以下是示例代码:

import cv2
import numpy as np
from sklearn.svm import SVC

def load_dataset():
    '''
    加载数据集
    '''
    # 加载正样本数据
    positive_images = []
    for i in range(100):
        image = cv2.imread('positive/{}.jpg'.format(i), 0)
        image = np.reshape(image, (20 * 20,))
        positive_images.append(image)

    # 加载负样本数据
    negative_images = []
    for i in range(200):
        image = cv2.imread('negative/{}.jpg'.format(i), 0)
        image = np.reshape(image, (20 * 20,))
        negative_images.append(image)

    # 将正负样本合并,打标签
    X = np.concatenate([positive_images, negative_images], axis=0)
    y = np.concatenate([np.ones(len(positive_images)), np.zeros(len(negative_images))])

    return X, y


def train_model():
    '''
    训练机器学习模型
    '''
    # 加载数据集
    X, y = load_dataset()

    # 训练模型
    model = SVC(kernel='linear', probability=True)
    model.fit(X, y)

    return model


def get_position(image, model):
    '''
    获取滑块位置
    '''
    row, col = image.shape
    stride = 5
    patches = []
    for i in range(0, row - stride, stride):
        for j in range(0, col - stride, stride):
            patch = image[i:i+stride, j:j+stride]
            patches.append(np.reshape(patch, (stride * stride, )))

    # 预测
    results = model.predict_proba(patches)[:, 1]
    results = np.reshape(results, (row // stride - 1, col // stride -1))
    max_prob = 0
    position = 0
    row, col = results.shape
    for i in range(row):
        for j in range(col):
            if i + 2 < row and j + 2 < col:
                sub_result = results[i:i+3, j:j+3]
                prob = np.mean(sub_result)
                if prob > max_prob:
                    max_prob = prob
                    position = (i + 1) * stride

    return position

# 加载机器学习模型
model = train_model()

# 加载验证码图片
image = cv2.imread('captcha.jpg', 0)

# 识别滑块位置
position = get_position(image, model)
print('缺口位置', position)

总结

通过学习本篇文章,我们了解了滑动验证码识别技术的原理和方法,并学会了使用Python进行滑动验证码的识别。无论是使用图像识别技术还是机器学习模型,都能够让我们愉快地完成爬虫任务,欢迎大家在实际应用中尝试。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python爬虫之验证码篇3-滑动验证码识别技术 - Python技术站

(0)
上一篇 2023年6月11日
下一篇 2023年6月11日

相关文章

  • 基于vue 动态菜单 刷新空白问题的解决

    那么让我们来详细讲解一下“基于Vue动态菜单刷新空白问题的解决”的完整攻略。 首先,我们需要了解静态菜单和动态菜单的区别。静态菜单是指在网站中写死的菜单,如果需要更改菜单内容或数量,就需要修改网站代码,并重新发布。而动态菜单是指在后台通过接口获取数据来动态生成菜单的方式,可以根据数据的变化而实现菜单的更新。 在Vue中,我们可以通过组件来实现动态菜单。常见的…

    JavaScript 2023年6月11日
    00
  • jquery对Json的各种遍历方法总结(必看篇)

    下面我来详细讲解一下”jquery对Json的各种遍历方法总结(必看篇)”的完整攻略。 简介 在前端开发中,我们经常会用到Json格式的数据。而jquery中提供了很多方法用于遍历Json数据。本文就对这些方法做了一个总结,供大家参考。 each方法 each方法是jquery中针对数组和对象的遍历方法,它接受一个函数作为参数,这个函数会在每个元素上被调用。…

    JavaScript 2023年5月27日
    00
  • JavaScript中如何对多维数组(矩阵)去重的实现

    JavaScript中对多维数组(矩阵)去重的实现,可以使用Set数据结构和Array.prototype.map方法相结合实现。相比遍历数组并用indexOf方法实现数组去重,Set结构和map方法的效率更高。下面是实现的步骤: 将多维数组转换成一维数组 let arr = [ [1, 2, 3], [2, 3, 4], [3, 4, 5] ]; let …

    JavaScript 2023年5月27日
    00
  • JavaScript实现短信倒计时60s

    当需要在网页中添加短信验证码的时候,我们通常需要一个倒计时的功能,限制60秒内只允许重新获取一次验证码。下面是JavaScript实现短信倒计时60s的攻略。 1. 倒计时基础框架 我们先来搭建倒计时的基本框架,HTML代码如下: <button id="btn">获取验证码</button> 需要注意的是,这里的…

    JavaScript 2023年5月27日
    00
  • JavaScript高级程序设计(第3版)学习笔记9 js函数(下)

    《JavaScript高级程序设计(第3版)学习笔记9 js函数(下)》一文主要讲解了 JavaScript 中函数的进阶应用,包括函数作为对象、闭包、函数自执行等内容,下面是具体的攻略: 1. 函数作为对象 在 JavaScript 中,函数同时也是对象,因此它们可以拥有属性和方法。函数的属性通常是直接在函数对象上定义,而方法则是定义在函数的原型对象上。 …

    JavaScript 2023年5月18日
    00
  • C#监测IPv4v6网速及流量的实例代码

    先给出完整的攻略目录,方便理清思路: 前置知识:C#网络库的使用 监测IPv4v6网速及流量的实现方法 示例1:监测本机流量并将数据保存至文件 示例2:通过Ping测试监测网络延迟 下面我就从这个目录入手,逐一给出详细的说明: 前置知识:C#网络库的使用 在监测网速和流量时,我们需要使用C#的网络库来进行网络通信相关操作。C#网络库主要包括Socket、We…

    JavaScript 2023年5月28日
    00
  • Web安全测试之XSS实例讲解

    Web安全测试是指对Web应用程序进行安全风险评估的过程。其中,XSS(Cross-site scripting)是一种常见的Web安全漏洞,攻击者通过注入脚本代码实现攻击。以下是对“Web安全测试之XSS实例讲解”的完整攻略: 第一步:寻找输入点 首先根据Web应用程序的业务逻辑找到需要输入的点,例如登录、注册、用户评论等。在这些输入点中,可能会存在输入过…

    JavaScript 2023年6月11日
    00
  • C#后台调用前台javascript的五种方法小结

    下面是详细讲解“C#后台调用前台javascript的五种方法小结”的完整攻略。 简介 在Web开发中,经常会需要在C#后台中调用前台的JavaScript函数,实现前后台数据的交互。本篇文章将介绍五种方法,分别是: RegisterClientScriptBlock:在页面中注册客户端脚本代码块; RegisterStartupScript:在页面中注册客…

    JavaScript 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部