专栏首页源懒由码python + selenium 爬虫模拟登录破解无原图滑动验证码

python + selenium 爬虫模拟登录破解无原图滑动验证码

爬虫模拟登录破解无原图滑动验证码: https://www.cnblogs.com/98WDJ/p/11050559.html

需求:部分网站在频繁的使用之后,会弹出滑块验证码(极验)。有别于过去,现在的原图并不会出现,因此较过去的思路转变为以下:

1、截取带缺口的图片;

2、寻找原图,并截图;

3、比较两张图片,寻找到缺口位置距离;

4、计算运动过程,并驱动浏览器移动滑块。

参考链接基本提供了1-3步的实现,第4步存在被识别为机器操作,需要进行更新(修正以后,目前成功率应该有50%以上),记录如下。

一、启动浏览器,配置option,以防被识别为自动化。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver import ActionChains
from PIL import Image
import numpy as np
import pandas as pd
import time

# 配置浏览器
options = webdriver.ChromeOptions()
# 此步骤很重要,设置为开发者模式,防止被各大网站识别出来使用了Selenium
options.add_experimental_option('excludeSwitches', ['enable-automation']) 

二、获取两张图片进行比较,通过网页分析发现。该标签,当display=block,opacity=1时,显示的为原图。

# 获取第一个图
img_name1 = r'../data/png/captcha2.png'
img_name2 = r'../data/png/captcha2_src.png'
img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]')))
img.screenshot(img_name1)

# 获取原图
browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
                          "x.style.display='block';"
                          "x.style.opacity=1"
                          )
img = wait.until(EC.presence_of_element_located((By.XPATH,'//canvas[@class="geetest_canvas_slice geetest_absolute"]')))
img.screenshot(img_name2)
# 变回来
browser.execute_script("var x=document.getElementsByClassName('geetest_canvas_fullbg geetest_fade geetest_absolute')[0];"
                          "x.style.display='none';"
                          "x.style.opacity=0"
                          )

三、计算两张图片差异,通过rgb一定的缺值进行判断缺口。

# 如何能找到滑块的位置
def get_distance(img1,img2):
    start_x=60#初始X
    threhold=60#阈值
    for x in range(start_x,img1.size[0]):
        for y in range(img1.size[1]):
            rgb1=img1.load()[x,y]
            rgb2=img2.load()[x,y]
            res1=abs(rgb1[0]-rgb2[0])
            res2=abs(rgb1[1]-rgb2[1])
            res3=abs(rgb1[2]-rgb2[2])
            if not (res1<threhold and res2<threhold and res3<threhold):
                return x-7#测试后-7可以提高成功率

四、计算模拟移动,根据自身的挪动特点,我一般的移动操作分为三个阶段(可根据自身特点进行设计)。

1:点击滑块以后,缓慢移动一下。约移动3次。

2:快速移动到缺口附件。大概0.3s。

3:到了缺口附近以后,缓慢靠近,然后在缺口处停留大概0.5秒以后释放。

# 将整个过程分为3段,总时长大概是1.2-1.6秒
# 第一段是启动阶段,第一次点击的时候,总会比较拘谨,慢速启动,大概消费t2(0.3)秒,s2为分段数
# 第二段则是很快到达缺口附近,大概剩余d3(5)距离处
# 第三段是缓慢对接,最后停在上面0.5秒
def get_tracks(distance,s1 = 2,t2 = 0.3,s2 = 3,d3 = 5):
    # 计算d1移动过程
    dtemp = 0
    track1 = []
    for i in range(s1):
        t = np.random.randint(low = 1, high=3)
        track1.append(t)
        dtemp = dtemp + t
    
    # 计算d2距离
    distance =distance - dtemp - d3
    
    track2 = []
    a = 2 * distance /(t2 ** 2)
    dtemp = 0
    for i in range(s2):
        # 计算每段行走
        ttemp1 = t2/s2 * (i + 1)
        ttemp2 = t2/s2 * i
        t = int(0.5 * a * (ttemp1 ** 2) - 0.5 * a * (ttemp2 ** 2) )
        track2.append(t)
        dtemp = dtemp + t
        
    #由于取整了,可以存在一点误差,调整d3
    d3 = distance - dtemp + d3
    print(d3)
    track3 = []
    s = 0
    while s < d3:
        t = np.random.randint(low = 1, high=3)
        if s + t >= d3:
            track3.append(d3 - s)
            break
        else:
            s = s + t
            track3.append(t)    
    return {"track1": track1, 'track2': track2, 'track3': track3}
%%time
# 计算路径,不行,这个会被识别为计算机
#获得滑块元素
geetest_slider_button=browser.find_element_by_class_name('geetest_slider_button')
#获得距离
img1 = Image.open(img_name1)
img2 = Image.open(img_name2)
distance=get_distance(img1,img2)
#获得步数
tracks_dic=get_tracks(distance,s1 = 2,t2 = 0.2,s2 = 3,d3 = 5)
#点击并按住    ActionChains(driver).click_and_hold(geetest_slider_button).perform()
track1=tracks_dic['track1']
track2=tracks_dic['track2']
track3=tracks_dic['track3']

最后,遍历执行动作链。

%%time
# 执行
ActionChains(browser).click_and_hold(geetest_slider_button).perform()
# 执行第一步
for t in track1:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
#停顿一会,更像人
time.sleep(0.2)
for t in track2:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
for t in track3:
    ActionChains(browser).move_by_offset(xoffset=t,yoffset=0).perform()
time.sleep(0.5)
# 松开
ActionChains(browser).release(geetest_slider_button).perform()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • python selenium 微信公众号历史文章随手一点就返回首页?郁闷之下只好将他们都下载下来。

    参照资料:selenium webdriver 如何添加cookie: https://www.cnblogs.com/sundahua/p/10202494....

    forxtz
  • sql serve2008是否自带互斥锁

    近期突然想到,一道珠海笔试题,让你写atm机的逻辑,当时想多了,以为重点是让你写清楚其中的事务互斥关系,当时也忘记数据库是否会自动互斥,从而不会出现脏数据。所以...

    forxtz
  • python 舆情分析 nlp主题分析 (1) 待续

    参考资料: https://blog.csdn.net/Eastmount/article/details/50891162 # 该博主有很多篇幅,解释算法原...

    forxtz
  • Django实战-生鲜电商-数据库事务

    在订单确认中,涉及到获取参数、校验参数;查询商品数据,判断是否为购物车的商品,遍历商品 id,获取商品信息;读取商品的数量,计算商品的金额,判断库存,需要用户的...

    小团子
  • android长截屏原理及实现代码

    小米系统自带的长截屏应该很多人都用过,效果不错。当长截屏时listview就会自动滚动,当按下停止截屏时,就会得到一张完整的截屏。

    砸漏
  • 边框的巧妙应用

    边框有一些特殊的属性,可以采用边框来实现对话框的效果,而且兼容性杠杠的,不过在ie6下面可能会遇到兼容性问题,在后面分析它。 首先,我们看看边框的组成结构: ...

    欲休
  • 小程序JS动态修改样式

    先写一个不怎么好看的demo,通过点击事件来控制view的元素属性,把背景改变成蓝色。

    王小婷
  • Java一次编译,到处运行如何实现的?

    Java是一种高级语言,要让计算机执行你撰写的Java程序,也得通过编译程序的编译。但是Java编译程序并不直接将Java源代码编译为相依于计算机平台的0、1序...

    葆宁
  • Java 动态字节码技术

    初学 Java 时,我对 IDEA 的 Debug 非常好奇,不止是它能查看断点的上下文环境,更神奇的是我可以在断点处使用它的 Evaluate 功能直接执行某...

    枕边书
  • Python:线程之定位与销毁

    我们有个了不起的后台程序,可以动态加载模块,并以线程方式运行,通过这种形式实现插件的功能。而模块更新时候,后台程序自身不会退出,只会将模块对应的线程关闭、更新代...

    Lin_R

扫码关注云+社区

领取腾讯云代金券