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技术站