首页 > 编程语言 >python+selenium+opencv验证滑块

python+selenium+opencv验证滑块

时间:2022-10-15 16:44:38浏览次数:69  
标签:滑块 img python cv2 driver opencv action qk

我们在使用selenium爬虫的时候在登录时经常会遇到滑块验证码问题,导致登录受阻,正所谓万事开头难。

登录就登录不进去更别提往后的操作的。今天以登录京东后台来演示下如何破解滑块。

一.登录

首先我们先进入京东后台登录页面,输入用户名和密码进入滑块页面

import time

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()

driver.implicitly_wait(10)  # 设置隐形等待
driver.maximize_window()
driver.get("https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fhome.jd.com%2F")
driver.find_element(by=By.XPATH, value="//a[contains(text(),'账户登录')]").click()
driver.find_element(by=By.ID, value="loginname").send_keys("1935762273")
driver.find_element(by=By.ID, value="nloginpwd").send_keys("13833979764")
driver.find_element(by=By.ID, value="loginsubmit").click()
time.sleep(2)

二.获取缺口图和滑块保存到本地

1)首先获取滑块图

我们可以发现滑块图是用base64加密过的,因此在获取img_url时需要base64解密才能将图片保存到本地

img_list = driver.find_elements(by=By.TAG_NAME, value="img")
hk_img = img_list[4].get_attribute("src")  # 获取定位滑块的src
hk_img = hk_img[22:]  # 截取所需要的url
with open("./img/hk.png", mode="wb") as f:
    f.write(base64.b64decode(hk_img))  # base64解密后保存到本地img下

2)获取缺口图

 缺口图的获取和滑块方法是一样的,这里直接贴代码了。

qk_img = img_list[3].get_attribute("src")  # 获取定位缺口的src
qk_img = qk_img[22:]  # 截取所需要的url
with open("./img/qk.png", mode="wb") as f:
    f.write(base64.b64decode(qk_img))  # base64解密后保存到本地img下
driver.quit()

三.opencv处理

将缺口图和滑块图保存到本地后工作量就已经完成一半了,离胜利还有半步之遥,接下来就是用opencv处

理图片计算出偏移量

1)安装opencv

pip install opencv-python

2)opencv处理图片计算偏移量

灰度化处理滑块/缺口图,这一步骤需要导包 :import cv2.cv2 as cv2

hk_img_01 = cv2.imread("./img/hk.png", 0)  # 灰度化
qk_img_01 = cv2.imread("./img/qk.png", 0)

获取滑块在缺口图中匹配的位置

late = cv2.matchTemplate(qk_img_01, hk_img_01, cv2.TM_CCOEFF_NORMED)

计算偏移量

loc = cv2.minMaxLoc(late)

我们打印loc可以发现最终给出来的值是四个,我们直接取最大的那个即可(71)

 我们得到的71这个数字其实还不是最终的偏移量,还需要获取到滑块图Rendered size和Intrinsic size

 拿获取的loc*Rendered/Intrinsic得到的才是最后要偏移的距离

y = int(loc[2][0] * 39 / 50)

四.模拟鼠标事件拖拽滑块

这一步超级简单,就直接copy代码了

action = ActionChains(driver)
action.click_and_hold(img_list[4])
action.move_by_offset(x, 0)
action.release().perform()

这里需要注意的是万事都不是绝对的,计算偏移量也是一样,不能达到100%成功,但也有个七八十,所以

模拟鼠标拖拽时加个while循环即可,这里就不做过多演示了。

五.破解反爬机制

当你执行到第四步的时候你会发现有时即使滑块和缺口对应上了,但还是会提示验证失败,这是因为京东代码含反

爬机制,检验出你使用的是selenium,所以给你干掉了。下面就来介绍下小编的反反爬之苦逼之路。

1)改变请求头设置无痕模式

当遇到上面的情况后第一时间想到的就是改变请求头,设置无痕模式,于是抱着试试的心态我写了如下代码。

option = webdriver.ChromeOptions()

option.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                    "Chrome/104.0.0.0 Safari/537.36") 
option.add_experimental_option("excludeSwitches", ["enable-automation"])
driver = webdriver.Chrome(options=option)

结果可想而知,苍天助error不助succeed。

2)模拟手动拖拽轨迹

一条路走不通那么就走第二条,在尝试多次后可以发现,selenium打开页面到验证滑块的时,这个时候手动去拖拽

滑块,最后可以拼接成功,那么就有一种可能,反爬机制不是一开始就检测出来的,而是在模拟鼠标拖拽时检测出

来的。那么我们只需要模拟手动推拽轨迹使其更像人为操作即可。下面是封装好的方法(网上copy的,如有侵权,

请告知删除)

def get_track(distance):
    # 移动轨迹
    track = []
    # 当前位移
    current = 0
    # 减速阈值
    mid = distance * 4 / 5
    # 计算间隔
    t = 0.2
    # 初速度
    v = 1
    while current < distance:
        if current < mid:
            # 加速度为2
            a = 4
        else:
            # 加速度为-2
            a = -3
        v0 = v
        # 当前速度
        v = v0 + a * t
        # 移动距离
        move = v0 * t + 1 / 2 * a * t * t
        # 当前位移
        current += move
        # 加入轨迹
        track.append(round(move))
    return track

这个方法如果高中物理学的不好的人就不要了解了,直接拿来用即可。下面贴下最后代码

action = ActionChains(driver)
    tracks = get_track(x)
    action.click_and_hold(img_list[4]).perform()
    for i in tracks:
        action.move_by_offset(i, 0).perform()
    action.move_by_offset(3, 0).perform()
    action.move_by_offset(-3, 0).perform()
    action.release().perform()
    time.sleep(3)

3)修改window.navigator.webdrive

正常来说第二种方法就可以跳过检测验证成功,那么在了解一种也不错呢,正所谓艺多不压身。

我们在手动进入登录页面时window.navigator.webdrive是为undefined的。但用selenium打开登录

页面时window.navigator.webdrive的值为true,所以在进入页面时我们需要修改该值,最简单的方法

加入一行代码即可。

option.add_argument("--disable-blink-features=AutomationControlled")

六.验证结果

很抱歉的说句未能成功,原因是什么呢,其实通过模拟手动拖拽轨迹是可以验证成功的,这个亲测有效,

但不知为何京东网站又做了什么骚操作,目前无法验证成功,这个会后续研究,有好的方法再更新。

七.源码

import time

from selenium import webdriver
from selenium.webdriver.common.by import By
import base64
import cv2.cv2 as cv2
from selenium.webdriver import ActionChains

option = webdriver.ChromeOptions()
# option.add_argument("--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
#                     "Chrome/104.0.0.0 Safari/537.36")
# option.add_experimental_option("excludeSwitches", ["enable-automation"])
# option.add_argument("--disable-blink-features=AutomationControlled")
driver = webdriver.Chrome(options=option)

driver.implicitly_wait(10)  # 设置隐形等待
driver.maximize_window()
driver.get("https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fhome.jd.com%2F")
driver.find_element(by=By.XPATH, value="//a[contains(text(),'账户登录')]").click()
driver.find_element(by=By.ID, value="loginname").send_keys("15161581519")
driver.find_element(by=By.ID, value="nloginpwd").send_keys("13633979764")
driver.find_element(by=By.ID, value="loginsubmit").click()
time.sleep(2)


def get_track(distance):
    # 移动轨迹
    track = []
    # 当前位移
    current = 0
    # 减速阈值
    mid = distance * 4 / 5
    # 计算间隔
    t = 0.2
    # 初速度
    v = 1
    while current < distance:
        if current < mid:
            # 加速度为2
            a = 4
        else:
            # 加速度为-2
            a = -3
        v0 = v
        # 当前速度
        v = v0 + a * t
        # 移动距离
        move = v0 * t + 1 / 2 * a * t * t
        # 当前位移
        current += move
        # 加入轨迹
        track.append(round(move))
    return track


while True:
    img_list = driver.find_elements(by=By.TAG_NAME, value="img")
    hk_img = img_list[4].get_attribute("src")  # 获取定位滑块的src
    hk_img = hk_img[22:]  # 截取所需要的url
    with open("./img/hk.png", mode="wb") as f:
        f.write(base64.b64decode(hk_img))  # base64解密后保存到本地img下

    qk_img = img_list[3].get_attribute("src")  # 获取定位缺口的src
    qk_img = qk_img[22:]  # 截取所需要的url
    with open("./img/qk.png", mode="wb") as f:
        f.write(base64.b64decode(qk_img))  # base64解密后保存到本地img下

    hk_img_01 = cv2.imread("./img/hk.png", 0)  # 灰度化
    qk_img_01 = cv2.imread("./img/qk.png", 0)
    late = cv2.matchTemplate(qk_img_01, hk_img_01, cv2.TM_CCOEFF_NORMED)  # 获取滑块在缺口图的位置
    loc = cv2.minMaxLoc(late)  # 获取位置
    x = int(loc[2][0] * 39 / 50)
    print(x)
    action = ActionChains(driver)
    tracks = get_track(x)
    action.click_and_hold(img_list[4]).perform()
    for i in tracks:
        action.move_by_offset(i, 0).perform()
    action.move_by_offset(3, 0).perform()
    action.move_by_offset(-3, 0).perform()
    action.release().perform()
    time.sleep(3)

 

 

 

 

文章来源:https://www.cnblogs.com/lihongtaoya/ ,请勿转载
部分参考:https://blog.csdn.net/m0_59874815/article/details/121195481

标签:滑块,img,python,cv2,driver,opencv,action,qk
From: https://www.cnblogs.com/lihongtaoya/p/16793699.html

相关文章

  • python学习:获取指定目录下所有文件名os.walk和os.listdir
    1.os.walk返回指定路径下所有文件和子文件夹中所有文件列表其中文件夹下路径如下:importosdeffile_name_walk(file_dir):forroot,dirs,filesinos.walk(f......
  • python中sort()函数跟sorted()函数的用法及区别
    一、描述sorted()函数是用来对某个对象进行排序操作的函数sorted()函数与sort()函数的区别是:sort只能用于列表对象(list),而sorted可以对所有可迭代对象进行排序。sort......
  • Python初学学习笔记
    本篇为新生实践课所留作业的学习笔记,记录我尚不熟悉的Python知识刷题页面  1.保留字即关键字,是Python语言中内部使用的单词,代表一定语义。例如:and、class、if、el......
  • python烟花代码
    python烟花代码 如下#-*-coding:utf-8-*-importmath,random,timeimportthreadingimporttkinterastkimportre#importuuidFireworks=[]maxFirewor......
  • Python库-pandas详解
    1.pandas介绍 pandas是用于数据挖掘的Python库 便捷的数据处理能力独特的数据结构读取文件方便封装了matplotlib的画图和numpy的计算pandas的数据结构Ser......
  • Python简单爬虫
    对大佬的有些修改,用大佬的编码转换那里老是出问题这个亲测可以#-*-coding:utf-8-*-importrequestsimportparselurl=""#小说网站response=requests.get(url)respo......
  • python提效小工具-统计xmind用例数量
    问题:做测试的朋友们经常会用到xmind这个工具来梳理测试点或写测试用例,但是xmind8没有自带的统计测试用例,其他版本的xmind有些自带节点数量统计功能,但也也不会累计最终的数......
  • aardio 调用 python将图片放上界面
    在aardio中显示图片目录在aardio中显示图片显示图片的控件使用IO库在aardio中使用plus显示图片的控件在aardio中我们显示图片也有对应的控件,这个空间就是高......
  • FreeBSD下开发Python插件并使用nuitka打包
    承接前面的文章https://www.cnblogs.com/passedbylove/p/16759512.htmlhttps://www.cnblogs.com/passedbylove/p/16756063.html自定义Python插件的setup.pyfromdistu......
  • [oeasy]python0007-Guido的简历
    Guido的简历......