一个有意思的滑块验证码(原图返回)
难度: ★☆☆☆☆ 1星
这个网站的注册页面:
https://beijing.tuitui99.com/zhuce.html
有一个神奇的滑块验证码:
看上去是一个滑块验证码,长得跟极验差不多,令人望而却步,然而当我们打开控制台观察其网络请求的时候,则发现其实是假的...
这是刷新验证码图片的请求:
可以看到图片大致分为三个部分,最上面是带缺口的背景图,中间是滑块图片,最下面是不带缺口的背景图,这就意味着如果我们把最上面带缺口的背景图和最下面不带缺口的图片做一个比对,它们第一个不同的像素所在的列就是上面图片中缺口所在的列。
再看这个刷新验证码请求的参数,这是个get请求,只有一个t参数,这个t 参数看上去像是从0到1之间的一个随机数,在刷新验证码的时候一般都会带上一个随机数以让验证码图片的缓存失效,这个参数我们可以先忽略它,如果等下发现不行再回来搞它。
然后就是提交验证码请求,我们先故意搞几个验证失败的,看下网络请求是怎样的:
请求是个get请求,只有一个tn_r参数,参数的值是一个数字,看上去像是缺口所在的列的x坐标,而响应内容似乎表示验证不通过的时候就返回“error”:
如果是滑块验证成功的:
则请求的响应是这样的:
OK,接下来就是编码实现了:
#!/usr/bin/env python3 # encoding: utf-8 """ @author: CC11001100 """ import io import logging import numpy import requests from PIL import Image LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s" logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) session = requests.session() def run(): url = "https://beijing.tuitui99.com/tncode.html" response = session.get(url) logging.info(f"获取验证码结果: {response.content}") image = Image.open(io.BytesIO(response.content)) matrix = numpy.asarray(image) x = find_lack_location(matrix) check_code(x) def find_lack_location(image_matrix): """ 在验证码图片中寻找 :param image_matrix: :return: """ # 从左往右栅格扫描,寻找第一个不相等的列的x坐标 for x in range(len(image_matrix[0])): # 高度为450px,存储了三张等高图片,则每张图片的高度为150 for offset in range(0, 150): image_1_y = 0 + offset image_2_y = 300 + offset # 如果发现这一列的像素点有不同的,则认为是滑块出现了 if ((image_matrix[image_1_y][x] != image_matrix[image_2_y][x]).any()): logging.info(f"寻找到缺块所在的列: {x}") return x def check_code(x): url = f"https://beijing.tuitui99.com/checkcode.html?tn_r={x}" response = session.get(url) logging.info(f"提交结果: {response.text}") if __name__ == "__main__": run()
运行结果:
仓库:
请注意爬虫文章具有时效性,本文写于2020-11-4日。