首先打开某东的网页。点击登录
挡住我们登录的第一道防线就是这个滑块验证码了。
首先我们分析一下呗
换一张看看
多换几张
第一张的图片怎么又出现了
看来图库是非常有限的
那么这样的滑块图片缺口位置确定就非常的简单了
首先看下图片的请求
非常明显就是这个请求
https://iv.jd.com/slide/g.html
下载了图片的滑块的base64编码和滑块所在纵坐标的位置y
首先我们写一个脚本将图片都下载到本地中
非常快我们下载了五百张左右的图片
可以看见基本背景已经重复的非常多了。仔细看一下某东的滑块背景仅有10张图
那么缺口位置就非常好的去定位了
我们能看到现在所有的背景图都是带缺口的
那么我们如何做到获得真正的背景图呢
这边我选择的是选两张缺口位置不一样的图各取一块然后拼接成一个完整的图片
这样我们获得了10张原始背景图
有的朋友看到这里应该比较清楚缺口如何去定位了
就是根据同背景图的滑块图片进行逐像素对比
图片的RGB像素如果改变较大那就是滑块缺口所在的坐标了
话不多说上代码(java代码)
首先我们如何确定两张图片是同一张呢
public static String getHash(BufferedImage bi) {
int[] rgb = new int[3];
int height = bi.getHeight();
int miny = bi.getMinY();
String hash_string = "";
for (int j = miny; j < height; j++) {
int pixel = bi.getRGB(0, j); // 下面三行代码将一个数字转换为RGB数字
rgb[0] = (pixel & 0xff0000) >> 16;
rgb[1] = (pixel & 0xff00) >> 8;
rgb[2] = (pixel & 0xff);
hash_string += rgb[0];
hash_string += rgb[1];
hash_string += rgb[2];
}
return DigestUtils.md5Hex(hash_string);
}
获取图片首位像素的字符串和的MD5值
如果相同则在这个场景下基本能确定是同个图片
private static String[] picStrings = {
"0cafdec4d059a547d9b515132dfeda9c.png",
"2e752832dd5775fb9b85ac539c21edb3.png",
"5d2a20ff27057c1dc919c3546a015773.png",
"6bc516221904aac0638a49e593961bd7.png",
"18d2593513d903c71ca604f896b9163b.png",
"9803b41933ddf82d222462237e4c9bb3.png",
"67010e410cdaf071b5bf72fa35c1d448.png",
"c3d0065ead7e43da9c057c81137d419e.png",
"6c26390570b6062d423bc05e45898cbb.png",
"c20fdaa0906d123629bade0e436903ce.png"};
public static Map<String, BufferedImage> getBufferedImageMap() {
if (bufferedImageMap == null) {
BufferedImage bi = null;
InputStream in = null;
bufferedImageMap = new HashMap<>();
for (int i = 0; i < picStrings.length; i++) {
try {
in = JdSlideEncrypt.class.getClassLoader().getResourceAsStream("jdPicData/" + picStrings[i]);
bi = ImageIO.read(in);
} catch (Exception e) {
LOG.error("bufferedImageMap创建出现异常" + e);
}
bufferedImageMap.put(getHash(bi), bi);
}
try {
if (in != null) {
in.close();
}
} catch (Exception e) {
LOG.error("bufferedImageMap创建出现异常" + e);
}
}
return bufferedImageMap;
}
获取所有背景图片仓库
然后就是最重要的一步了
逐像素对比
public static int parseCaptcha(BufferedImage currentBi, Map<String, BufferedImage> bufferedImageMap, String y) {
int x = 0;
int width = currentBi.getWidth();
String hashcode = JdPicDateUtils.getHash(currentBi);
BufferedImage baseBi = bufferedImageMap.get(hashcode);
if (baseBi == null) {
return 0;
}
int[] currentRgb = new int[3];
int[] baseRgb = new int[3];
int currentY = Integer.parseInt(y);
for (int j = 0; j < width; j++) {
int currentPixel = currentBi.getRGB(j, currentY + 20); // 下面三行代码将一个数字转换为RGB数字
int basePixel = baseBi.getRGB(j, currentY + 20); // 下面三行代码将一个数字转换为RGB数字
currentRgb[0] = (currentPixel & 0xff0000) >> 16;
currentRgb[1] = (currentPixel & 0xff00) >> 8;
currentRgb[2] = (currentPixel & 0xff);
baseRgb[0] = (basePixel & 0xff0000) >> 16;
baseRgb[1] = (basePixel & 0xff00) >> 8;
baseRgb[2] = (basePixel & 0xff);
if (Math.abs(baseRgb[0] - currentRgb[0]) + Math.abs(baseRgb[1] - currentRgb[1]) + Math.abs(baseRgb[2] - currentRgb[2]) > 50) {
x = j;
break;
}
}
return x;
}
如果找到就返回X
大功告成啦
并且带着大家去一步一步解析某东滑块JS代码
jd滑块第二集
https://blog.csdn.net/cyz52/article/details/102170870
代码在git上,如果有帮助到你,欢迎start
github地址
本文章纯属技术探讨学习
防止不法用途
轨迹代码为旧版本需要自行优化
有任何问题可以联系邮箱[email protected]