当前位置: 首页 > 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;一个接口只有方法的特征没有方法的…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

vue3 字体颜色设置的多种方式

在Vue 3中设置字体颜色可以通过多种方式实现&#xff0c;这取决于你是想在组件内部直接设置&#xff0c;还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法&#xff1a; 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

WebRTC从入门到实践 - 零基础教程

WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC&#xff1f; WebRTC&#xff08;Web Real-Time Communication&#xff09;是一个支持网页浏览器进行实时语音…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...