极验验证码破解(三)

一、网站http://www.gsxt.gov.cn滑动验证码概述
二、极验验证码破解-抓包分析
三、极验验证码破解-搭建本地验证码服务
四、极验验证码破解-分析geetest.js,得到所需参数
五、极验验证码破解-Track的获取
六、极验验证码破解-获取背景图片及缺口距离d的计算
七、极验验证码破解-总结
参考文献
运行截图

2017.8.21 代码以上传,可供参考

https://github.com/FanhuaandLuomu/geetest_break

五、极验验证码破解-Track的获取

  1. Track的生成可以根据图片缺口的距离d,使用随机函数随机采样生成。比如d=120,则我们控制总拖动时间为t(t一般小于3s),则可以每很小的时间内(每次随机时间,如10ms)移动一小段随机距离,最后在时刻t时正好移动到d。但考虑人拖动会有先加速在减速的特点(或许还有其他特点),geetest的服务器可能会识别到时机器所为,我们很难找到人行为的轨迹特点并且难以模拟,因此生成轨迹不太可行(也许可行,但代价较大)。
  2. 我们提出另一种方法替代Track的生成,即手工事先存储备用Track。验证码图片总长大概250左右,由于我们已经实现了在Console中打印Track的js,因此我们可以多次刷新http://localhost:8000/页面,得到不同缺口位置的验证码,手动拖动至缺口处,保存Console中的Track。
  3. 经过试验发现,缺口位置大多停留在中间位置,并且拖动误差在3以内都可以接受。因此我们可以用当前位置d的Track来代替d-1和d+1的Track(如缺口位置120,则119和121的Track可以不用测试,直接使用120的Track)。这样大大减少了刷新页面获取Track的次数,我收集的Track列表如下:
    极验验证码破解(三)_第1张图片
    极验验证码破解(三)_第2张图片
    为了方便统计,我按个位数将Track存放在10个文件中。
    我们将所有的Track整合为dict(t_dict.pkl),格式如下:
    {k1:v1},其中k1为缺口位置,v1为Track(字符串形式)。
    这里写图片描述
    这里写图片描述
    至此我们得到Track备用列表,我们可以根据实际的缺口位置获得相应的Track值,下一节我们将会讲解如何得到缺口距离验证码左边的相对距离d。

六、极验验证码破解-获取背景图片及缺口距离d的计算

  1. 我们首先寻找图片的来源。回忆分析get.php?的时候,看到过“fullbg”的出现,因此很大可能背景图片信息是通过get.php?传来的。查看Response如下:
    这里写图片描述
    这里写图片描述
    根据图片的url打开图片:
    极验验证码破解(三)_第3张图片
    可以发现图片已经乱码,这是因为返回的图片是局部重合产生的。
    查看验证码图片的审查元素:
    极验验证码破解(三)_第4张图片
    这里写图片描述
    可以发现,展示的图片是从原始乱码图片中多次截取小段,合成而成的。具体的合成方式如background-position所示。

如background-position:-157px,-58px。则该小段图片为源乱码图片的(157,58,157+10,58+58)。根据上述分析,我么可以还原bg和fullbg的非乱码图片(即所看见的背景图片)。
极验验证码破解(三)_第5张图片
极验验证码破解(三)_第6张图片
我们通过比较两张图片的像素值,即可得到缺口的位置,缺口左上角横坐标的值即为d。我们封装了get_dist函数如下:

# 计算缺口距离
def get_dist(image1,image2):
    # 合并图片使用
    location_list=cPickle.load(open('location_list.pkl'))

    jpgfile1=cStringIO.StringIO(urllib2.urlopen(image1).read())
    new_image1=get_merge_image(jpgfile1,location_list)

    new_image1.save('image1.jpg')

    jpgfile2=cStringIO.StringIO(urllib2.urlopen(image2).read())
    new_image2=get_merge_image(jpgfile2,location_list)

    new_image2.save('image2.jpg')

    i=0
    for i in range(260):
        for j in range(116):
            if is_similar(new_image1,new_image2,i,j)==False:
                # 找到缺口  返回缺口的横坐标i 
                # 因为图片是水平移动 所以不需要缺口的纵坐标
                return i

函数其它细节请参见项目源码。

七、极验验证码破解-总结

  1. 至此,geetest验证码的关键技术点已经讲解完,有没有感觉号称使用深度学习技术进行人机验证的滑动验证码也不过如此。最近我会在Github上开源所有代码,希望得到大家的指点。
  2. 当时做这个项目大概断断续续做了两星期左右(2017.03),开始是参照网上教程使用selenium控制鼠标来实现,后来发现鼠标移动的速度太机械化,成功率太低(滑动到缺口处,但被识别为机器行为)。所以,我采取了退而求其次的方法,避免对轨迹路径的生成,直接使用已经成功验证的历史轨迹来作为当前轨迹。经过试验,这种方法成功率接近100%,且复杂度不高,历史轨迹单独存在硬盘,可定期更新(以防止轨迹被封)。
  3. 最近(2017.07)突然想写个文档教程分享技术,算是个学习笔记,也算是对自己曾经努力的记载。该文档断断续续写了4个晚上的时间,欢迎大家阅读并指正。
  4. 最后附上Github地址,里面有一些小爬虫和NLP相关的项目,欢迎围观。https://github.com/FanhuaandLuomu

参考文献

  1. http://blog.csdn.net/paololiu/article/details/52514504
  2. https://zhuanlan.zhihu.com/p/22866110?refer=windev
  3. https://zhuanlan.zhihu.com/p/22404294
    (向上述作者致谢)

运行截图

Python geetest_spider.py (暂未开源,敬请期待…)

注意:要爬取的企业列表写在searchword_list。
这里写图片描述
极验验证码破解(三)_第7张图片
极验验证码破解(三)_第8张图片
极验验证码破解(三)_第9张图片
极验验证码破解(三)_第10张图片

你可能感兴趣的:(Python-爬虫)