高阶爬虫实战:破解极验滑动验证码

2023-10-25 00:30

本文主要是介绍高阶爬虫实战:破解极验滑动验证码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

编程狗 编程大牛技术分享平台 640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

今天给大家带来的是极验验证码的selenium破解之法,是不是有点小激动呢,小伙伴们等不及了,让我们赶紧直入主题吧。

虎X网注册

这次我们是拿虎X开刀,注册账号的时候需要滑动图片到缺口位置,这种验证码我们现在也经常遇到,这个就不用详细介绍了吧 

640?wx_fmt=png&wxfrom=5&wx_lazy=1

针对这种验证码我们首先确定了使用selenium模拟滑动破解方式,selenium鼠标移动点击拖动都比较简单,那么问题就在于拖动多少距离,眼睛看起来很直观,但是程序怎么获取呢?利用图像识别......,额,这个只能想想了吧。不如看看网页源码或者请求信息,看看有没有有效的信息。

查看网页信息

鼠标右键点击到图片上,查看元素 

640?wx_fmt=png

这一瞬间的图片,还好我二十几年的麒麟臂没白练,我们看看元素查看到的都是什么东西 640?wx_fmt=png

这看起来有点奇怪哦,有个图片链接,还有位置信息,而且还那么多,先把图片链接拷贝到浏览器里访问下看看 

640?wx_fmt=png 

WTF,这是什么鬼?注意到那个像猪尾巴一样的6了吗?还有那个小箭头,跟上面完整图片对比一下,发现把箭头挪动到小6旁边,猪尾巴就成功了。当然你仔细观察的话,还有其他的比如文字也是类似。那么我们可以确认这张图片应该是被打乱的,如果我们可以把它拼起来,是不是就离计算缺口位置比较近了。现在我们应该要注意到元素查看里后面的位置信息了,那么多,看起来应该跟这个打乱顺序有点关系吧。我们来确认一下。我的想法是这样子的,既然这个位置和拼图有关,而且再看我们上面麒麟臂截的图,我再标记一下 

640?wx_fmt=png

 我们点击查看元素的时候,浏览器会帮我们突出显示一下,本来我是在图片上点击查看的,按照我的想法,它不是应该整张图片突出显示一下吗?看起来好像不是这么回事,只有那么一小部分,而且上面还有元素信息,宽高类名,再回去看看图3,位置坐标里,前面应该是x轴,后面是y轴,y轴只有58和0,再根据图2一看,图片分为上下两部分,再数一下div的数量,26块,每一块宽10x高58。按照这个来算的话,那么整个图片的宽就是260,高116,用截图工具去拉一下图片的宽高,基本吻合 

640?wx_fmt=gif

接下来就是确定怎么拼了。这里很抱歉的告诉大家,猪没了,等我写到这里再去查看网页的时候,图片已经刷新了。所以接下来的截图可能不一样,在这里提前跟大家说明一下。反正就是找特征点嘛,每个图片应该都有的。先随便找一个特征点,查看元素,看它定位到那个div元素那里,然后再看看后面的位置。基本就是这样,所以我们找图片既然和位置有关,那么我们最好选一些位置明显的地方,比如中间,或者两边。 

640?wx_fmt=png 

这个差不多算中间位置了吧,查那么一点点无所谓了 

640?wx_fmt=png

我去,这......跟我想的不太一样呀,再找两张看看,代表性及其强烈的 

640?wx_fmt=png 

640?wx_fmt=png

640?wx_fmt=png 640?wx_fmt=png

为了防止有人说我水字数,另外两个角就不截图了。到这一步可能有人纳闷了,为啥?你刚才说图片宽度260,为什么坐标里出现了289这样的坐标,这不就是超标了吗?一开始我也有这样的疑惑,可能我们看到图片比实际的小,也许人家在图片外面还留了边框呢,我一开始是这么想的。但是这个坐标是前面url里面的图片坐标,然后我就去看了一下图4 

640?wx_fmt=gif 

这个图片尽然比较大,坐标问题有答案了,但是这个跟260有什么关系呢?打乱的图片比较大,拼好的小,那它是怎么拼的呢?幸好我们看到了一个比较有用信息 

640?wx_fmt=png

640?wx_fmt=png

看到这个-1px了吗?它成功引起了我的注意,因为按照我的想法,如果是从拼图里拿出一部分拼成一个完成图片的话,那么最左边拿出来的图片,应该是从(0,0),(0,58),但是我们看到的是(1,0),(1,58),y值还是比较符合我们的预期的,第一部分从0开始,高58,第二部分从58开始。但是x值有点问题,按照1作为起点,那第二个应该是11,因为宽度是10,这是确定的,我们找找看

640?wx_fmt=png

是13,难道每一小块前面都多余了1个像素?按照这种的话也应该是12呀,按照这种方式我们继续找一找剩下的,通过分析我们发现每个小块+12作为下一个小块的起点。这样的话左右各去掉一个像素,宽度不就是10了吗?而且每个小块是12,26个是312,跟我们看到的拼图大小差不多,说明我们分析的是正确的。按照元素里提供的坐标,取宽度为10的大小即可。接下来分析一下这些坐标的意义。

坐标分析

分析一下我们图9到图12的截图,首先说图9,我本来觉得它x、y应该是0,就算不是0,也应该是各位数字吧,结果的y是58,这个算到下半截图片区域了,x是157,跑中场去了。图11呢,你的x应该在300左右,y应该100以上吧,结果y是0,到上半段,x是205,在中场偏后,离守门员还远呢。这是怎么肥事?不过我们发现了,图9在元素里是第一个,图11在元素里是最后一个,再结合坐标前面的y值全是58,后面的y值全是0,符合我们上半段下半段颠倒的想法了,然后你再分别查看图9右边/图11左边的元素就会发现,和元素里面div的顺序一样。到这里就差不多了。

总结一下:最终的图片就是把拼图,即图4,按照x=157、y=58、w=10、h=58截取出来,放在上半部分第一个位置,x=145、y=58、w=10、h=58截取出来放在上半部分第二个位置,紧挨着第一个,以此类推,拼成一张整图。 

640?wx_fmt=png 

这个就是我拼出来的,恩,很好,很不错嘛小伙子。不过好像哪里不对,缺口嘞。仔细看看网页元素 

640?wx_fmt=png原来一个是fullbg,一个是cutbg,这个名字就很有寓意嘛,那就好了,再把cutbg拼一下看看 

640?wx_fmt=png 

这回就对上了。现在的问题就变成怎么计算缺口位置了

缺口位置

我觉得可能会有计算两张图片不同位置的方式吧,度娘来一发,然后获取了python实战===用python对比两张图片的不同,然后发现了ImageChops.difference这个接口,结果你们知道的,不准确,为啥捏?仔细看拼好的两张图,除了缺口还有其他地方不一样呀。看到图16缺口后面那个阴影没,让我的心里蒙上了一层阴影,再观察其他的图片,基本都有类似的,这可怎么办?这在后面还好说,如果是在前面呢,那不就计算到阴影里去了嘛。如果这个对比有一个容差就好了,我以前用按键精灵的时候好像就有这种嘛,这个好不智能呀。既然它是对比像素,我直接取像素对比一下不就得了,而且我还不给它用==,给它一个范围,如果色差在这个范围内就算一样了,这样不就有容差了吗?这个缺口一般都非常明显,而阴影跟背景又很模糊,应该是可行的。思路就是获取图片的宽高,然后一个像素一个像素的遍历对比。

色差

这个色差怎么确定?一种方式就是调试,这种是比较麻烦的,还有一种方式就是获取多张图片,全图和缺陷图,然后使用取色工具,取对应位置的颜色值,确定一个大概范围。距离确定了,下面就是移动了

selenium模拟移动

selenium的模拟操作网上介绍很多,这里我们只要确认需要哪些接口就行了。 ActionChains方法:

  • movetoelement(to_element) - 鼠标移动到某个元素

  • clickandhold(on_element =None) - 点击鼠标左键,不松开

  • movebyoffset(xoffset,yoffset) - 鼠标从当前位置移动到某个坐标

  • release(on_element = None) - 在某个元素位置松开鼠标左键

  • perform() - 执行操作,记住这个很重要,调用上面的方法后,一定要执行perform才能真正执行

selenium的操作我就不详细描述了,这里用到的都是比较简单的用法。

原理分析就完了,这一次必须要贴代码了,否则可能很多人完成不了,也有利于大家的理解。

由于篇幅有限,下面为部分代码,完整代码请关注公众号“编程狗”后回复“0419”获取

 
  1. # -*- coding: utf-8 -*-

  2. import random

  3. import time, re

  4. from selenium import webdriver

  5. from selenium.common.exceptions import TimeoutException

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

  7. from selenium.webdriver.support.wait import WebDriverWait

  8. from selenium.webdriver.support import expected_conditions as EC

  9. from selenium.webdriver.common.action_chains import ActionChains

  10. from PIL import Image

  11. import requests

  12. from io import BytesIO

  13. class HuXiu(object):

  14.    def __init__(self):

  15.        chrome_option = webdriver.ChromeOptions()

  16.        # chrome_option.set_headless()

  17.        self.driver = webdriver.Chrome(executable_path=r"/usr1/webdrivers/chromedriver", chrome_options=chrome_option)

  18.        self.driver.set_window_size(1440, 900)

  19.    def visit_index(self):

  20.        self.driver.get("https://www.huxiu.com/")

  21.        WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//*[@class="js-register"]')))

  22.        reg_element = self.driver.find_element_by_xpath('//*[@class="js-register"]')

  23.        reg_element.click()

  24.        WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_slider_knob gt_show"]')))

  25.        # 进入模拟拖动流程

  26.        self.analog_drag()

  27.    def analog_drag(self):

  28.        #鼠标移动到拖动按钮,显示出拖动图片

  29.        element = self.driver.find_element_by_xpath('//div[@class="gt_slider_knob gt_show"]')

  30.        ActionChains(self.driver).move_to_element(element).perform()

  31.        time.sleep(3)

  32.        # 刷新一下极验图片

  33.        element = self.driver.find_element_by_xpath('//a[@class="gt_refresh_button"]')

  34.        element.click()

  35.        time.sleep(1)

  36.        # 获取图片地址和位置坐标列表

  37.        cut_image_url, cut_location = self.get_image_url('//div[@class="gt_cut_bg_slice"]')

  38.        full_image_url, full_location = self.get_image_url('//div[@class="gt_cut_fullbg_slice"]')

  39.        # 根据坐标拼接图片

  40.        cut_image = self.mosaic_image(cut_image_url, cut_location)

  41.        full_image = self.mosaic_image(full_image_url, full_location)

  42.        # 保存图片方便查看

  43.        cut_image.save("cut.jpg")

  44.        full_image.save("full.jpg")

  45.        # 根据两个图片计算距离

  46.        distance = self.get_offset_distance(cut_image, full_image)

  47.        # 开始移动

  48.        self.start_move(distance)

  49.        # 如果出现error

  50.        try:

  51.            WebDriverWait(self.driver, 5, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_ajax_tip gt_error"]')))

  52.            print("验证失败")

  53.            return

  54.        except TimeoutException as e:

  55.            pass

  56.        # 判断是否验证成功

  57.        try:

  58.            WebDriverWait(self.driver, 10, 0.5).until(EC.element_to_be_clickable((By.XPATH, '//div[@class="gt_ajax_tip gt_success"]')))

  59.        except TimeoutException:

  60.            print("again times")

  61.            time.sleep(5)

  62.            # 失败后递归执行拖动

  63.            self.analog_drag()

  64.        else:

  65.            # 成功后输入手机号,发送验证码

  66.            self.register()

  67.    # 获取图片和位置列表

  68.    def get_image_url(self, xpath):

  69.        link = re.compile('background-image: url\("(.*?)"\); background-position: (.*?)px (.*?)px;')

  70.        elements = self.driver.find_elements_by_xpath(xpath)

  71.        image_url = None

  72.        location = list()

  73.        for element in elements:

  74.            style = element.get_attribute("style")

  75.            groups = link.search(style)

  76.            url = groups[1]

  77.            x_pos = groups[2]

  78.            y_pos = groups[3]

  79.            location.append((int(x_pos), int(y_pos)))

  80.            image_url = url

  81.        return image_url, location

  82. (部分代码)

这个移动movebyoffset,我之前的y值也是随机的[-5,5],我觉得这个模拟会更真实一点,总会上下抖动的嘛,结果就是因为这个考虑的太人性了,识别率非常低,改了好多范围,更大的、更小的,结果最后不偏移,竟然识别率奇高。TMD考虑的太人性化了竟然识别不了,我也是醉了。最后再把执行效果发一下吧 

640?wx_fmt=gif


作者星星在线,一个从妹子图到爬虫爱好者的猿生历程

https://www.jianshu.com/u/680e0e38ddc9

打赏作者

640?wx_fmt=jpeg

最近热门文章

如何用Python做一个骚气的程序员

用Python爬取陈奕迅新歌《我们》10万条评论的新发现

机器学习算法KNN简介及实现

Python有趣的解包用法

用Python分析苹果公司股价数据

Nginx+uwsgi部署Django应用

Python自然语言处理分析倚天屠龙记

Python 3.6实现单博主微博文本、图片及热评爬取

获取本文完整代码请长按扫描二维码关注公众号“编程狗”后回复“0419

640?wx_fmt=jpeg

▼ 点击下方阅读原文免费成为社区会员

这篇关于高阶爬虫实战:破解极验滑动验证码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/278784

相关文章

Python与DeepSeek的深度融合实战

《Python与DeepSeek的深度融合实战》Python作为最受欢迎的编程语言之一,以其简洁易读的语法、丰富的库和广泛的应用场景,成为了无数开发者的首选,而DeepSeek,作为人工智能领域的新星... 目录一、python与DeepSeek的结合优势二、模型训练1. 数据准备2. 模型架构与参数设置3

Java实战之利用POI生成Excel图表

《Java实战之利用POI生成Excel图表》ApachePOI是Java生态中处理Office文档的核心工具,这篇文章主要为大家详细介绍了如何在Excel中创建折线图,柱状图,饼图等常见图表,需要的... 目录一、环境配置与依赖管理二、数据源准备与工作表构建三、图表生成核心步骤1. 折线图(Line Ch

Python自动化处理手机验证码

《Python自动化处理手机验证码》手机验证码是一种常见的身份验证手段,广泛应用于用户注册、登录、交易确认等场景,下面我们来看看如何使用Python自动化处理手机验证码吧... 目录一、获取手机验证码1.1 通过短信接收验证码1.2 使用第三方短信接收服务1.3 使用ADB读取手机短信1.4 通过API获取

Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)

《Python爬虫selenium验证之中文识别点选+图片验证码案例(最新推荐)》本文介绍了如何使用Python和Selenium结合ddddocr库实现图片验证码的识别和点击功能,感兴趣的朋友一起看... 目录1.获取图片2.目标识别3.背景坐标识别3.1 ddddocr3.2 打码平台4.坐标点击5.图

Java使用Tesseract-OCR实战教程

《Java使用Tesseract-OCR实战教程》本文介绍了如何在Java中使用Tesseract-OCR进行文本提取,包括Tesseract-OCR的安装、中文训练库的配置、依赖库的引入以及具体的代... 目录Java使用Tesseract-OCRTesseract-OCR安装配置中文训练库引入依赖代码实

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程

《在Java中使用ModelMapper简化Shapefile属性转JavaBean实战过程》本文介绍了在Java中使用ModelMapper库简化Shapefile属性转JavaBean的过程,对比... 目录前言一、原始的处理办法1、使用Set方法来转换2、使用构造方法转换二、基于ModelMapper

Java实战之自助进行多张图片合成拼接

《Java实战之自助进行多张图片合成拼接》在当今数字化时代,图像处理技术在各个领域都发挥着至关重要的作用,本文为大家详细介绍了如何使用Java实现多张图片合成拼接,需要的可以了解下... 目录前言一、图片合成需求描述二、图片合成设计与实现1、编程语言2、基础数据准备3、图片合成流程4、图片合成实现三、总结前

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下