当前位置: 首页 > news >正文

selenium+opencv实现模拟登陆(滑块验证码)

很多网站登录登陆时都要用到滑块验证码,在某些场景例如使用爬虫爬取信息时常常受到阻碍,想着用opencv的模板匹配试试能不能实现模拟登陆。本来觉得网上资料多应该还蛮容易,但实际上手还是搞了蛮久,在这里记录一下整个流程,网站无所谓主要是要有滑动验证码:

环境

python 3.9, selenium和Opencv相关依赖,用于抓取图片的requests包,具体安装这里不多讲了,其中selenium用的火狐版本。

selenium登录网站

整体流程就是这个样子:访问网站->点击登录->输入账号密码->搞定滑块验证->登录网站,其中最大的难点是滑块验证码,但在此之前我们当然要先让selenium自动打开网站把账号密码输好,我们通过find_element()方法定位输入框之后执行操作,元素的各个属性F12就可以找到:

代码如下:

options = webdriver.FirefoxOptions()
driver = webdriver.Firefox(options=options)
driver.get('网址')
driver.find_element("link text", "登录").click()
name = driver.find_element("id", "name-input")
name.send_keys("账号######") # 输入账号
pw = driver.find_element("id", "password-input")
pw.send_keys("密码#########") # 输入密码
driver.find_element("id", "submit").click() # 提交

requests抓取验证码图片


为了做后续处理我们需要把滑块验证码相关图片抓到本地,网上关于滑块验证码这块很多都是用原图和有缺口的图对比来确定缺口位置的,但是我并没有找到原图,这里用到的是有缺口的背景图和滑块图,如下:

滑块图: 

 有缺口的背景图:


这里爬图是selenium定位之后用requests包爬的,注意验证码和登陆界面不在一个iframe里,selenium记得切到对应iframe才能定位到图片,代码如下:

driver.switch_to.frame('tcaptcha_iframe')# 切换iframe
img = driver.find_element("id", "slideBg").get_attribute('src')
headers = {'Accept': "application/json, text/plain, */*",'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"
} # 请求头
r = requests.get(img, headers=headers)
with open('img.png', 'wb') as f:f.write(r.content)
block = driver.find_element("id", "slideBlock").get_attribute('src')
r = requests.get(block, headers=headers)
with open('block.png', 'wb') as f:f.write(r.content)

 OpenCV识别缺口位置


接下来就是重点,如何确定缺口位置来定位滑动验证码该往哪滑。这里主要用到OpenCV的模板匹配。 首先对滑块也就是稍后匹配时用到的模板进行处理,这里主要就是把形状轮廓提取出来然后去掉多余的东西,先把原图变成灰度图:

tpl_gray = cv2.cvtColor(tpl, cv2.COLOR_BGR2GRAY)


可以看到边缘有一圈阴影部分,我们需要把周围这圈去掉,遍历找到黑色像素点把它变成和周围一样。

width, height = tpl_gray.shapefor h in range(height):for w in range(width):if tpl_gray[w, h] == 0:tpl_gray[w, h] = 96

 处理后变成了这样,然后把中间主体部分涂黑,也就是将图片二值化。

binary = cv2.inRange(tpl_gray, 96, 96)  # 二值化
kernel = np.ones((8, 8), np.uint8)
template = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel) # 去白色噪点

 处理完毕得到理想的模板图:

 接下来对带有缺口的背景图进行处理,这个过程稍微麻烦一点,不过思路还是比较清晰的,还是先转化成灰度图再二值化,这里有一个问题,不同验证码图片之间差距很大,有的颜色很显眼,有的却很清淡,比如下面这两差别太大了,这就导致在二值化的过程中很难有一个固定的参数。

 这里我根据图片的平均灰度值设定了几个区间,对不同区间的验证码图片传入不同参数进行二值化:

def avg_mean(img):mean_val, _, _, _ = cv2.mean(img)print("平均灰度:", mean_val)return mean_valdef match(img):gauss = cv2.GaussianBlur(img, [5, 5], 0)img_gray = cv2.cvtColor(gauss, cv2.COLOR_BGR2GRAY)cv2.imshow("111", img_gray)if avg_mean(img) > 140: # 二值化ret, target = cv2.threshold(img_gray, 105, 255, cv2.THRESH_BINARY)elif avg_mean(img) > 102:ret, target = cv2.threshold(img_gray, 95, 255, cv2.THRESH_BINARY) else:ret, target = cv2.threshold(img_gray, 85, 255, cv2.THRESH_BINARY)

 处理过的结果大概像这样:

 效果还是不错的,清晰的凸显了缺口位置,最后把背景图和模板传入opencv的模板匹配方法,记录下匹配到的坐标即可。

result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
left_up = max_loc
print(left_up)
right_down = (left_up[0] + height, left_up[1] + width)
cv2.rectangle(img, left_up, right_down, (0, 0, 255), 2)
cv2.imshow('res', img)

 这里框出来看看效果:

 模拟拖动滑块

识别出位置之后就要算出滑块移动了多少距离,我们可以看到滑块初始状态距离边缘有26个像素:

 同时抓下来的图片相比在网页中放大了一倍,所以真实滑动距离是: 

(left_up - 26*2)/2

于是用selenium的actionchains模拟拖动滑块:

def drag_block(l):drag = driver.find_element("id", "tcaptcha_drag_button")ActionChains(driver).click_and_hold(on_element=drag).perform()ActionChains(driver).move_to_element_with_offset(to_element=drag, xoffset=l, yoffset=0).perform()ActionChains(driver).release().perform()

 这样整个流程就搞定了,理论上这样简单粗暴的自动拖过去在很多时候会不奏效,还需要模拟人手动拖动,不过因为我做测试的时候直接就成功了,所以没写下去,整体思路大概是加速减速停几秒或者中间触发几个mouse_up(),mouse_down()事件。

脚本示例:

下面是测试时用到的脚本,selenium部分和主函数,拿某个CTF靶场做的测试,仅供参考,根据实际网站不同肯定得改改:

import time
import requestsfrom selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChainsimport block_locdef drag_block(l):drag = driver.find_element("id", "tcaptcha_drag_button")ActionChains(driver).click_and_hold(on_element=drag).perform()ActionChains(driver).move_to_element_with_offset(to_element=drag, xoffset=l, yoffset=0).perform()ActionChains(driver).release().perform()def login_in(username, password):headers = {'Accept': "application/json, text/plain, */*",'User-Agent': "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36"}driver.get('网址')driver.find_element("link text", "登录").click()name = driver.find_element("id", "name-input")name.send_keys(username)pw = driver.find_element("id", "password-input")pw.send_keys(password)driver.find_element("id", "submit").click()time.sleep(2)driver.switch_to.frame('tcaptcha_iframe')img = driver.find_element("id", "slideBg").get_attribute('src')r = requests.get(img, headers=headers)with open('img.png', 'wb') as f:f.write(r.content)block = driver.find_element("id", "slideBlock").get_attribute('src')r = requests.get(block, headers=headers)with open('block.png', 'wb') as f:f.write(r.content)if __name__ == '__main__':options = webdriver.FirefoxOptions()driver = webdriver.Firefox(options=options)user = "##########"pw = "############"login_in(user, pw)image = "img.png"tpl = "block.png"length = block_loc.match(image, tpl)print(length)drag_block(length)

 Opencv部分:

import cv2
import numpy as npdef avg_mean(img):mean_val, _, _, _ = cv2.mean(img)print("平均灰度:", mean_val)return mean_valdef match(image, temp):img = cv2.imread(image)tpl = cv2.imread(temp)tpl_gray = cv2.cvtColor(tpl, cv2.COLOR_BGR2GRAY)# cv2.imshow("111", tpl_gray)width, height = tpl_gray.shapefor h in range(height):for w in range(width):if tpl_gray[w, h] == 0:tpl_gray[w, h] = 96binary = cv2.inRange(tpl_gray, 96, 96)kernel = np.ones((8, 8), np.uint8)template = cv2.morphologyEx(binary, cv2.MORPH_OPEN, kernel)# cv2.imshow('tpl', template)print(img.shape)gauss = cv2.GaussianBlur(img, [5, 5], 0)img_gray = cv2.cvtColor(gauss, cv2.COLOR_BGR2GRAY)# cv2.imshow("111", img_gray)if avg_mean(img) > 140:ret, target = cv2.threshold(img_gray, 105, 255, cv2.THRESH_BINARY) # 二值化elif avg_mean(img) > 102:ret, target = cv2.threshold(img_gray, 95, 255, cv2.THRESH_BINARY)  # 二值化else:ret, target = cv2.threshold(img_gray, 80, 255, cv2.THRESH_BINARY)# cv2.imshow('target', target)result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)left_up = max_locprint(left_up)right_down = (left_up[0] + height, left_up[1] + width)cv2.rectangle(img, left_up, right_down, (0, 0, 255), 2)# cv2.imshow('res', img)length = (left_up[0] - 26*2)/2return length

相关文章:

selenium+opencv实现模拟登陆(滑块验证码)

很多网站登录登陆时都要用到滑块验证码,在某些场景例如使用爬虫爬取信息时常常受到阻碍,想着用opencv的模板匹配试试能不能实现模拟登陆。本来觉得网上资料多应该还蛮容易,但实际上手还是搞了蛮久,在这里记录一下整个流程&#xf…...

辽宁申请互联网医院牌照流程

辽宁申请互联网医院牌照流程|沈阳市|大连市|鞍山市|抚顺市|本溪市|丹东市|锦州市|营口市|阜新市|辽阳市|盘锦市|铁岭市|朝阳市|葫芦岛市   很多的人对互联网医院都不是很了解,也不太清楚互联网医院牌照怎么申请,其实牌照申请每个地区都不太一样&#x…...

java实现布隆过滤器

什么是布隆过滤器 布隆过滤器(Bloom Filter)是1970年由布隆提出来的。 它实际上是由一个很长的二进制数组一系列hash算法映射函数,用于判断一个元素是否存在于集合中。 布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和…...

gitlab部署及整合Jenkins持续构建(三)nexus私服的安装及实战、linux安装mysql

文章目录敏捷持续集成是什么?linux安装jdk和maven安装jdk安装mavenlinux安装nexus3.xnexus私服的使用编译安装mysql可能遇到的问题使用cmake时报错敏捷持续集成是什么? 持续集成是一种软件开发实践,即团队开发成员经常集成他们的工作&#x…...

一、Java基础(2)

本章概要 异常的分类及处理 异常的概念异常的分类处理异常的方式 反射机制 动态语言的概念反射机制的概念反射的作用Java 的反射 API反射的过程创建对象的两种方式Method 的 invoke 方法 1.2 异常的分类及处理 1.2.1 异常的概念 异常指在方法不能按正常方式完成时&#xf…...

软件设计师重要知识点——第一章——计算机组成与体系结构

目录 1.1数据的表示 1.2数值表示范围 1.3浮点的运算 1.4计算机结构 1.5计算机体系结构分类——Flynn 1.6指令的基本概念 1.7寻址方式 1.8CISC与RISC 1.9流水线 1.10层次化存储结构 1.11Cache 1.12主存——编址与计算 1.13总线 1.14串联系统与并联系统 1.15N模混…...

编程学习心得

我来写一些,我关于编程的简单认识吧。 我觉得编程是一门艺术,也是一项技能,需要不断地学习和练习。无论是初学者还是有经验的开发人员,都需要耐心和恒心,才能够成为一名优秀的程序员。以下是一些关于编程学习的心得和…...

web获取媒体流

1. 下面例子演示了录屏和截图功能&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport"…...

代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些、01背包问题,你该了解这些 滚动数组、 416. 分割等和子集

打卡第42天&#xff0c;搞搞01背包。 今日任务 01背包问题&#xff0c;你该了解这些&#xff01;01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组416.分割等和子集 背包问题1.0 &#xff1a;0-1 背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weig…...

【Android】JNI静态与动态注册介绍

JNI的两种注册机制&#xff1a;静态注册和动态注册. 一、JNI介绍 JNI(Java Native Interface)&#xff0c;即Java本地接口&#xff0c;JNI是Java调用Native 语言的一种特性。通过JNI可以使得Java与C/C机型交互. 方式&#xff1a; 静态注册动态注册&#xff1a;需要提供Java中…...

【算法题解】22. 接雨水

这是一道 困难 题 题目来自&#xff1a; https://leetcode.cn/problems/trapping-rain-water/ 题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,…...

集合详解之(四)集合的遍历

文章目录&#x1f412;个人主页&#x1f3c5;JavaSE系列专栏&#x1f4d6;前言&#xff1a;&#x1f380;ArrayList集合forEach()方法遍历&#x1f380;for循环遍历&#xff08;针对List集合&#xff09;&#x1fa85;增强for循环&#xff08;也支持Set集合&#xff09;&#x…...

【I2C】通用驱动i2c-dev分析

文章目录1. 前言2. i2c-dev驱动的注册过程3. open_i2c_dev函数分析4. set_slave_addr函数分析5. i2c_read_bytes函数分析1. 前言 前面分析i2c-tool测试工具就是基于drivers/i2c/i2c-dev.c驱动来实现的。i2c-dev驱动在加载时会遍历所有的I2C总线(i2c_bus_type)上所有注册的adap…...

用GPT-4写代码不用翻墙了?Cursor告诉你:可以~~

目录 一、介绍 二、使用方法 三、其他实例 1.正则表达式 2.自动化测试脚本 3.聊聊技术 一、介绍 Cursor主要功能是根据用户的描述写代码或者进行对话&#xff0c;对话的范围仅限技术方面。优点是不用翻墙、不需要账号。Cursor基于GPT模型&#xff0c;具体什么版本不祥&#…...

硬件语言Verilog HDL牛客刷题day03 时序逻辑部分

1.VL21 根据状态转移表实现时序电路 1.题目&#xff1a; 某同步时序电路转换表如下&#xff0c;请使用D触发器和必要的逻辑门实现此同步时序电路&#xff0c;用Verilog语言描述。 2.解题思路 2.1 首先同步时序电路 &#xff0c; 时钟上升沿触发&#xff0c; 复位信号rst 低电…...

day31 ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和 在本次的题目中&#xff0c;我们使用了贪心算法来解决三个问题&#xff1a;分发饼干、摆动序列、最大子序和。这三个问题都可以使用贪心算法来解决&#xff0c;而且贪心算法的时间复杂度相对较低&#xff0c;能够在较短的…...

MobTech 秒验|本机号码一键登录会泄露隐私吗

本机号码一键登录是一种新型的应用登录方式&#xff0c;它可以利用运营商的数据网关认证能力&#xff0c;实现手机号免密登录&#xff0c;提高用户体验和转化率&#xff0c;降低验证成本和流失率。本机号码一键登录支持三大运营商号码认证&#xff0c;3秒内完成手机号验证&…...

2023年供销合作社研究报告

第一章 行业概况 1.1 供销合作社概述 中华全国供销合作总社&#xff0c;是中华人民共和国全国供销合作社的联合组织。中华全国供销合作总社的前身可以追溯到1949年11月成立的中央合作事业管理局。在新中国成立初期&#xff0c;供销合作社就基本形成了自上而下、覆盖全国的组织…...

【ansible】实施任务控制

目录 实施任务控制 一&#xff0c;循环&#xff08;迭代&#xff09;--- loop 1&#xff0c;利用loop----item循环迭代任务 2&#xff0c;item---loop循环案例 1&#xff0c;定义item循环列表 2&#xff0c;通过变量应用列表格式 3&#xff0c;字典列表&#xff08;迭代嵌套子…...

49天精通Java,第11天,java接口和抽象类的异同,default关键字

目录一、什么是接口二、接口的特点三、接口和类的区别四、接口和抽象类的区别五、接口的声明方式六、default默认方法大家好&#xff0c;我是哪吒。 一、什么是接口 Java接口是一系列方法的声明&#xff0c;是一些方法特征的集合&#xff0c;一个接口只有方法的特征没有方法的…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

Python 训练营打卡 Day 47

注意力热力图可视化 在day 46代码的基础上&#xff0c;对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

Leetcode33( 搜索旋转排序数组)

题目表述 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...