上篇我们借助 tesserocr 库解决了图片码的识别验证,但在实际生活中,用得更多的是滑动验证,这篇就来解决滑动验证的问题
滑动验证
大部分网站都采用的是滑动验证,就是拖动滑块拼接图片,其中又大都采用极验(http://www.geetest.com/)所提供的技术,官方网页如下
本篇案例选用哔哩哔哩动画验证登录(https://passport.bilibili.com/login)
所需工具
chromedriver:浏览器驱动,可以理解为一个没有界面的chrome浏览器
selenium:用于模拟人对浏览器进行点击、输出、拖拽等操作,就相当于是个人在使用浏览器,也常常用来应付反爬虫措施,配合chromedriver使用,使用方法直接粘大神写的:https://cuiqingcai.com/5630.html
Image模块:提供很多对图片进行处理的方法的库,用法请查看https://www..com/kongzhagen/p/6295925.html
解决思路
1. 获取验证图片
通过访问登录页面,分析源码找到完整图片和带滑块缺口的图片 ,通过 selenium 键入登录信息
2. 获取缺口位置
通过对比原始的图片和带滑块缺口的图片的像素,计算出滑块缺口的位置,得到所需要滑动的距离
3.模拟拖动
利用selenium进行对滑块的拖拽,注意模仿人的行为:先快后慢,有个对准过程
案例步骤
第一大步:获取验证图片
1.初始化一些需要用到的参数
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
# 初始化
def init():
# 定义为全局变量,方便其他模块使用
global url, browser, username, password, wait
# 登录界面的url
url = 'https://passport.bilibili.com/login'
# 实例化一个chrome浏览器
browser = webdriver.Chrome()
# 用户名
username = '***********'
# 密码
password = '***********'
# 设置等待超时
wait = WebDriverWait(browser, 20)
2.通过 selenium 键入登录信息
(by the way:之前用 post 提交表单做过模拟登录,其实用selenium模拟人键入登录信息和点击提交也可以成功登录,但问题是selenium相率太低,所以一般能不用selenium就不用)
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
# 登录
def login():
# 打开登录页面
browser.get(url)
# 获取用户名输入框
user = wait.until(EC.presence_of_element_located((By.ID, 'login-username')))
# 获取密码输入框
passwd = wait.until(EC.presence_of_element_located((By.ID, 'login-passwd')))
# 输入用户名
user.send_keys(username)
# 输入密码
passwd.send_keys(password)
3.获取验证图片
通过分析源码找到原始完整图片和带滑块缺口的图片
from urllib.request import urlretrieve
from bs4 import BeautifulSoup
import re
from PIL import Image
# 获取图片信息
def get_image_info(img):
'''
:param img: (Str)想要获取的图片类型:带缺口、原始
:return: 该图片(Image)、位置信息(List)
'''
# 将网页源码转化为能被解析的lxml格式
soup = BeautifulSoup(browser.page_source, 'lxml')
# 获取验证图片的所有组成片标签
imgs = soup.find_all('div', {'class': 'gt_cut_'+img+'_slice'})
# 用正则提取缺口的小图片的url,并替换后缀
img_url = re.findall('url\(\"(.*)\"\);', imgs[0].get('style'))[0].replace('webp', 'jpg')
# 使用urlretrieve()方法根据url下载缺口图片对象
urlretrieve(url=img_url, filename=img+'.jpg')
# 生成缺口图片对象
image = Image.open(img+'.jpg')
# 获取组成他们的小图片的位置信息
position = get_position(imgs)
# 返回图片对象及其位置信息
return image, position
但是这里有一个问题,验证图片是由两行许多的小图片组成的,而这些小图片不是按顺序排列的,这样就无法计算滑块缺口的位置了