
一、前言
爬虫最大的敌人之一是什么?没错,验证码!Geetest作为提供验证码服务的行家,市场占有率还是蛮高的。遇到Geetest提供的滑动验证码怎么破?
一种方法是分析它的js加密方法,通过大量抓包分析找到它的返回参数,直接自动生成需要的参数即可,这种方法工程量大一些,并且官方js脚本一升级,就得重新分析,耗时耗力。
今天为大家介绍的一种方法是,通过Selenium模拟用户滑动解锁。这个方法的优势在于简单,方便更新。但是它的缺点也很明显,速度慢,并且不能制作成api接口的形式。
授人予鱼不如授人予渔,接下来就为大家呈现本教程的精彩内容。不过,在阅读本篇文章之前,请确保你已经掌握网络爬虫基础,如果不具备爬虫基础,请到我的CSDN专栏学习。然后,再来阅读本文,我的专栏地址:点我查看
二、先睹为快

左侧显示的为自动识别过程,右边是一些打印信息。
三、实战分析
我们以国家企业信用信息公式系统为例,这是一个企业信息查询的网站,在每次查询都需要进行一次验证码识别。它所使用的就是GEETEST验证码,它的URL:点我查看
这个网站是这个样子的:

1、过程分析
要想把大象装冰箱,总共分几步?
那么,现在思考一个问题,通过Selenium模拟用户滑动解锁,总共分几步?请停在这里,思考五分钟,再继续阅读!
我们先公布一个粗率的答案:
- 使用Selenium打开页面。
- 匹配到输入框,输入要查询的信息,并点击查询按钮。
- 读取验证码图片,并做缺口识别。
- 根据缺口位置,计算滑动距离。
- 根据滑动距离,拖拽滑块到需要匹配的位置。
其实,将每个步骤拆分开来一点一点实现并不难,接下来进入正文。
2、实战开始
第一步:使用Selenium打开网页,并输入信息,点击查询按钮。
这部分内容很简单,Selenium基础性的东西我不再讲解,如有不懂,请看我专栏的Selenium相关内容。
编写代码如下:
# -*-coding:utf-8 -*-
EC
WebDriverWait
By
webdriver
:
:
;
)
)
keyword
:
打开浏览器,并输入查询内容
)
)
)
)
)
:
# 打开浏览器
)
:
)
)
)

第二步:保存验证码图片
我们审查元素找打图片的地址,审查结果如下:

可以看到,图片是很多图片合成的,也就是说你只保存所有地址的图片是不行的。它是通过background-position的方法进行合成的。每一个图片是乱的,这个怎么搞?很简单,抓取这些图片的链接,然后根据链接的图片,再合成这张没有缺口的图片,获取缺口图的方法也是如此,都是自己合成。
编写代码如下:
# -*-coding:utf-8 -*-
random
image
BytesIO
Image
webdriver
By
ActionChains
WebDriverWait
EC
urllib
BeautifulSoup
urlretrieve
:
:
;
)
)
keyword
6
:
)
)
:
获取网页截图
:return: 截图对象
)
)
screenshot
:
获取验证码位置
:return: 验证码位置元组
)
)
location
size
]
)
:
获取验证码图片
:return: 图片对象
)
)
)
)
)
captcha
:
获取验证码图片
:return: 图片的location信息
]
]
:
)
)
)
)
)
]
]
:
}
)
)
)
:
}
)
)
)
)
)
)
)
fullbg_location_list
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
)
)
)
)
)
:
获取滑块
:return: 滑块对象
:
:
)
break
:
)
slider
:
获取缺口偏移量
:param img1: 不带缺口图片
:param img2: 带缺口图片
:return:
43
:
:
:
i
left
left
:
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
# 取两个图片的像素点
]
]
60
:
True
:
False
:
根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹
# 移动轨迹
]
# 当前位移
0
# 减速阈值
5
# 计算间隔
0.2
# 初速度
0
:
:
# 加速度为正2
2
# 加速度为负3
3
# 初速度v0
v
# 当前速度v = v0 + at
t
# 移动距离x = v0t + 1/2 * a * t^2
t
# 当前位移
move
# 加入轨迹
)
track
:
拖动滑块到缺口处
:param slider: 滑块
:param track: 轨迹
:return:
)
:
)
)
)
)
)
:
# 打开浏览器
)
# 保存的图片名字
'bg.jpg'
'fullbg.jpg'
# 获取图片
)
# 根据位置对图片进行合并还原
)
)
# 点按呼出缺口
)
# 获取缺口位置
)
)
)
)
)
)
:
)
)
)
)
运行效果如下:

可以看到,运行之后,我们已经顺利生成了两张图片,一个是缺口图,另一个是非缺口图。
第三步:计算缺口距离
根据缺口图和非缺口图,通过比对图像的像素点的大小区别,找到缺口位置。
编写代码如下:
# -*-coding:utf-8 -*-
EC
WebDriverWait
By
urlretrieve
webdriver
BeautifulSoup
image
re
:
:
'http://bj.gsxt.gov.cn/sydq/loginSydqAction!sydq.dhtml'
)
)
keyword
:
打开浏览器,并输入查询内容
)
)
)
)
)
:
获取验证码图片
:return: 图片的location信息
]
]
:
)
)
)
)
)
]
]
:
}
)
)
)
:
}
)
)
)
)
)
)
)
fullbg_location_list
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
获取缺口偏移量
:param img1: 不带缺口图片
:param img2: 带缺口图片
:return:
43
:
:
:
i
left
left
:
# 打开浏览器
)
# 保存的图片名字
'bg.jpg'
'fullbg.jpg'
# 获取图片
)
# 根据位置对图片进行合并还原
)
)
# 获取缺口位置
)
)
:
)
)
)
运行结果如下:

这样我们就计算除了缺口位置,接下来就是根据缺口位置,滑动滑块到相应位置。
第四步:计算滑动轨迹
我们可以使用瞬间移动,直接在1s内移动到目标位置,结果就是”被吃了“。

匀速直线运动,匀速直线运动大法好!果不其然,还是”被吃了“,继续尝试。

模仿抖抖病患者运动,颤颤巍巍,如履薄冰,估计geetest服务器认为是我外婆在操作吧。

虽然这个方法偶尔会成功,但成功率极低。最好的方法是什么呢?
模拟人的运动!你想一下,人在滑动滑块的初期是不是速度快,但是当要接近缺口位置的时候,会减速,因为我得对准缺口位置啊!这怎么实现呢?使用我们初中学过的物理知识:
当前速度公式为:
v = v0 + a * t
其中,v是当前速度,v0是初始速度,a是加速度,t是时间。我们刚开始的让加速大,当过了中间位置,降低加速度。使用这个移动过程,移动滑块到缺口位置。
编写代码如下:
# -*-coding:utf-8 -*-
EC
WebDriverWait
By
urlretrieve
webdriver
BeautifulSoup
image
re
:
:
'http://bj.gsxt.gov.cn/sydq/loginSydqAction!sydq.dhtml'
)
)
keyword
6
:
打开浏览器,并输入查询内容
)
)
)
)
)
:
获取验证码图片
:return: 图片的location信息
]
]
:
)
)
)
)
)
]
]
:
}
)
)
)
:
}
)
)
)
)
)
)
)
fullbg_location_list
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
# 取两个图片的像素点
]
]
60
:
True
:
False
:
获取缺口偏移量
:param img1: 不带缺口图片
:param img2: 带缺口图片
:return:
43
:
:
:
i
left
left
:
根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹
# 移动轨迹
]
# 当前位移
0
# 减速阈值
5
# 计算间隔
0.2
# 初速度
0
:
:
# 加速度为正2
2
# 加速度为负3
3
# 初速度v0
v
# 当前速度v = v0 + at
t
# 移动距离x = v0t + 1/2 * a * t^2
t
# 当前位移
move
# 加入轨迹
)
track
:
# 打开浏览器
)
# 保存的图片名字
'bg.jpg'
'fullbg.jpg'
# 获取图片
)
# 根据位置对图片进行合并还原
)
)
# 获取缺口位置
)
)
)
)
)
:
)
)
)
运行效果如下:

第五步:移动滑块
根据返回的每次滑动的距离,我们移动滑块至缺口位置。
编写代码如下:
# -*-coding:utf-8 -*-
EC
WebDriverWait
By
urlretrieve
webdriver
BeautifulSoup
image
re
:
:
'http://bj.gsxt.gov.cn/sydq/loginSydqAction!sydq.dhtml'
)
)
keyword
6
:
打开浏览器,并输入查询内容
)
)
)
)
)
:
获取验证码图片
:return: 图片的location信息
]
]
:
)
)
)
)
)
]
]
:
}
)
)
)
:
}
)
)
)
)
)
)
)
fullbg_location_list
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
根据位置对图片进行合并还原
:filename:图片
:location_list:图片位置
)
)
]
]
:
:
)
:
)
)
0
:
)
]
0
:
)
]
)
new_im
:
判断两个像素是否相同
:param image1: 图片1
:param image2: 图片2
:param x: 位置x
:param y: 位置y
:return: 像素是否相同
# 取两个图片的像素点
]
]
60
:
True
:
False
:
获取缺口偏移量
:param img1: 不带缺口图片
:param img2: 带缺口图片
:return:
43
:
:
:
i
left
left
:
根据偏移量获取移动轨迹
:param distance: 偏移量
:return: 移动轨迹
# 移动轨迹
]
# 当前位移
0
# 减速阈值
5
# 计算间隔
0.2
# 初速度
0
:
:
# 加速度为正2
2
# 加速度为负3
3
# 初速度v0
v
# 当前速度v = v0 + at
t
# 移动距离x = v0t + 1/2 * a * t^2
t
# 当前位移
move
# 加入轨迹
)
track
:
获取滑块
:return: 滑块对象
:
:
)
break
:
)
slider
:
拖动滑块到缺口处
:param slider: 滑块
:param track: 轨迹
:return:
)
:
)
)
)
)
)
:
# 打开浏览器
)
# 保存的图片名字
'bg.jpg'
'fullbg.jpg'
# 获取图片
)
# 根据位置对图片进行合并还原
)
)
# 获取缺口位置
)
)
)
)
)
# 点按呼出缺口
)
# 拖动滑块到缺口处
)
:
)
)
)
)
运行上述代码,即实现滑动验证码破解,再看下那个nice的瞬间吧。

五、总结
如果破解极验验证码困难 可以有一个挺好的解决方案 http://jiyandoc.c2567.com/