• 最新版腾讯防水墙(二代)识别


    2022最新版腾讯防水墙(二代)识别

    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    * 验证码地址:https://007.qq.com/online.html
    * 使用OpenCv模板匹配
    * 成功率90%左右
    * Java + Selenium + OpenCV
    
    • 1
    • 2
    • 3
    • 4

    最近不少爬虫界面的朋友发现,原来可以识别腾讯防水墙的代码报错了, 怎么回事 ?
    原来是腾讯防水墙做了升级

    产品样例
    背景图
    在这里插入图片描述和工具体混在一起的滑动图
    在这里插入图片描述截取图:
    在这里插入图片描述

    改进主要特点:
    1 将滑块图片混合在工具条中,透明度不同,外边加了边框
    2 iframe , 名字有原来的 tcaptcha_iframe ,变为 tcaptcha_iframe_dy

    分析:
    关键点在于滑块的变化,由于滑块混合,第一步肯定要做切割,
    切割完后如果简单做二值化, 就会形成外框 ,这样下一步的就无法做模板匹配

    在这里插入图片描述
    在这里插入图片描述
    掌握了特点, 就有了解决的思路,办法总比困难多
    最后完美解决,识别率也不太高, 在 99% 左右吧

    来吧!展示!

    结果图1 : 五边形
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述在这里插入图片描述 结果图2 : 四边形
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    结果图3 :

    在这里插入图片描述在这里插入图片描述在这里插入图片描述

    注意!!!
    · 在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别。
    模拟滑动代码↓↓↓

    /**
    	 * 模拟人工移动
    	 * @param driver
    	 * @param element页面滑块
    	 * @param distance需要移动距离
    	 */
    	public static void move(WebDriver driver, WebElement element, int distance) throws InterruptedException {
    		int randomTime = 0;
    		if (distance > 90) {
    			randomTime = 250;
    		} else if (distance > 80 && distance <= 90) {
    			randomTime = 150;
    		}
    		List<Integer> track = getMoveTrack(distance - 2);
    		int moveY = 1;
    		try {
    			Actions actions = new Actions(driver);
    			actions.clickAndHold(element).perform();
    			Thread.sleep(200);
    			for (int i = 0; i < track.size(); i++) {
    				actions.moveByOffset(track.get(i), moveY).perform();
    				Thread.sleep(new Random().nextInt(300) + randomTime);
    			}
    			Thread.sleep(200);
    			actions.release(element).perform();
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    	/**
    	 * 根据距离获取滑动轨迹
    	 * @param distance需要移动的距离
    	 * @return
    	 */
    	public static List<Integer> getMoveTrack(int distance) {
    		List<Integer> track = new ArrayList<>();// 移动轨迹
    		Random random = new Random();
    		int current = 0;// 已经移动的距离
    		int mid = (int) distance * 4 / 5;// 减速阈值
    		int a = 0;
    		int move = 0;// 每次循环移动的距离
    		while (true) {
    			a = random.nextInt(10);
    			if (current <= mid) {
    				move += a;// 不断加速
    			} else {
    				move -= a;
    			}
    			if ((current + move) < distance) {
    				track.add(move);
    			} else {
    				track.add(distance - current);
    				break;
    			}
    			current += move;
    		}
    		return track;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    看操作,no bb,直接上代码

    /**
    	 * v2 版本
    	 * 
    	 * @param driver
    	 * @return
    	 */
    	public RetEntity moveExec(WebDriver driver, boolean isLocal) {
    		File bFile = null;
    		File sFile = null;
    		RetEntity retEntity = new RetEntity();
    		retEntity.setRet(-1);
    		try {
    
    			// 获取到验证区域
    			WebElement iframe = ChromeDriverManager.waitElement(driver, By.id("tcaptcha_iframe_dy"), 100);
    
    			if (iframe == null) {
    				System.out.println("moveExec() tcaptcha_iframe|timeout!!!");
    				retEntity.setMsg("tcaptcha_iframe|timeout!!");
    				return retEntity;
    			}
    			driver.switchTo().frame(iframe);
    			sleep(500);
    
    			// 获取带阴影的背景图
    			WebElement wegSlideBg = driver.findElement(By.id("slideBg"));
    			String cssValue = wegSlideBg != null ? wegSlideBg.getCssValue("background-image") : null;
    			String bgUrl = (cssValue != null && cssValue.contains("\"")) ? cssValue.split("\"")[1] : null;
    			if (bgUrl == null) {
    				retEntity.setMsg("bgUrl=" + bgUrl);
    				return retEntity;
    			}
    			Long time = System.currentTimeMillis();
    			// 获取小图 URL (替换img_index=1为 img_index=0)
    			String slUrl = bgUrl.replaceAll("img_index=1", "img_index=0");
    			System.out.println("bgUrl=" + bgUrl);
    			System.out.println("slUrl=" + slUrl);
    			bFile = new File(dataPath + time + "-b.png");
    			sFile = new File(dataPath + time + "-s.png");
    			int getMode = 0;
    			Map<String, byte[]> retMap = (getMode == 0) ? getTwoImg(driver, bgUrl, slUrl, bFile, sFile) : getTwoImgOpen(driver, bgUrl, slUrl, bFile, sFile);
    			if (retMap != null) {
    				byte[] bigBytes = retMap.get("big");
    				byte[] smallBytes = retMap.get("small");
    				String distanceStr = null, width = null;
    				String ckSum = GenChecksumUtil.genChecksum(bigBytes);
    				String[] outArray = openCv2.getOpenCvDistance(ckSum, bigBytes, smallBytes, "tencent_v2", 3);
    				distanceStr = (outArray != null && outArray.length >= 2) ? outArray[1] : null;
    				width = (outArray != null && outArray.length >= 2) ? outArray[0] : null;
    				Double left = 27.0 * 672 / 340;// 起点距左边距离
    				Double act = (Double.parseDouble(distanceStr) - left - Double.parseDouble(width)) * 340.0 / 672.0;
    				Integer distance = act.intValue();
    				System.out.println("moveExec()  distance(" + distanceStr + ")=" + distance);
    				if (distance == null || distance <= 0) {
    					return retEntity;
    				}
    				if (getMode != 0)
    					driver.switchTo().frame(iframe);
    				WebElement moveElemet = ChromeDriverManager.waitElement(driver, By.className("tc-slider-normal"), 500);
    				sleep(500);
    				// 滑动
    				GeetCanvasApi.move(driver, moveElemet, distance);
    				sleep(400);
    				// 滑动结果
    				String gtInfo = ChromeDriverManager.waitElement(driver, By.id("statusSuccess"), 100).getText();
    				if (gtInfo == null || "".equals(gtInfo)) {
    					sleep(200);
    					gtInfo = ChromeDriverManager.waitElement(driver, By.id("statusError"), 100).getText();
    				}
    				System.out.println("moveExec() gtInfo=" + gtInfo);
    				if (gtInfo.contains("验证成功")) {
    					retEntity.setRet(0);
    					retEntity.setMsg(gtInfo);
    					logger.info(retEntity.toString());
    				} else if (gtInfo.contains("再试一次") || gtInfo.contains("恍惚了") || gtInfo.contains("半路丢了")) {
    					retEntity.setRet(-1);
    					retEntity.setMsg("失败");
    				}
    			} else {
    				logger.error("retMap=" + retMap);
    				retEntity.setMsg("retMap=" + retMap);
    				return retEntity;
    			}
    			return retEntity;
    		} catch (Exception e) {
    			StringBuffer er = new StringBuffer("moveExec() " + e.toString() + "\n");
    			for (StackTraceElement elment : e.getStackTrace())
    				er.append(elment.toString() + "\n");
    			logger.error(er.toString());
    			System.out.println(er.toString());
    			retEntity.setMsg(er.toString());
    			return retEntity;
    		} finally {
    			if (retEntity.getRet() == 0) {
    				System.out.println("moveExec() del file...");
    				if (bFile != null)
    					bFile.delete();
    				if (sFile != null)
    					sFile.delete();
    			}
    		}
    	}
    
    	private Map<String, byte[]> getTwoImg(WebDriver driver, String bgUrl, String slUrl, File bFile, File sFile) {
    		try {
    			FileUtils.copyURLToFile(new URL(bgUrl), bFile);
    			FileUtils.copyURLToFile(new URL(slUrl), sFile);
    			BufferedImage sBI = ImageIO.read(sFile);
    			sBI = sBI.getSubimage(135, 478, 129, sBI.getHeight() - 478);
    			ImageIO.write(sBI, "png", sFile);
    			byte[] bigBytes = FileUtils.readFileToByteArray(bFile);
    			byte[] smallBytes = FileUtils.readFileToByteArray(sFile);
    			Map<String, byte[]> retMap = new HashMap<String, byte[]>();
    			retMap.put("big", bigBytes);
    			retMap.put("small", smallBytes);
    			return retMap;
    		} catch (Exception e) {
    			StringBuffer er = new StringBuffer("getTwoImgOpen() " + e.toString() + "\n");
    			for (StackTraceElement elment : e.getStackTrace())
    				er.append(elment.toString() + "\n");
    			logger.error(er.toString());
    			System.out.println(er.toString());
    			return null;
    		}
    	}
    
    
    /**
    	 * 
    	 * @param mat
    	 *            二值化图像
    	 */
    	public static void binaryzation(Mat mat) {
    		int BLACK = 0;
    		int WHITE = 255;
    		int ucThre = 0, ucThre_new = 127;
    		int nBack_count, nData_count;
    		int nBack_sum, nData_sum;
    		int nValue;
    		int i, j;
    		int width = mat.width(), height = mat.height();
    		// 寻找最佳的阙值
    		while (ucThre != ucThre_new) {
    			nBack_sum = nData_sum = 0;
    			nBack_count = nData_count = 0;
    
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; i++) {
    					nValue = (int) mat.get(j, i)[0];
    
    					if (nValue > ucThre_new) {
    						nBack_sum += nValue;
    						nBack_count++;
    					} else {
    						nData_sum += nValue;
    						nData_count++;
    					}
    				}
    			}
    			nBack_sum = nBack_sum / nBack_count;
    			nData_sum = nData_sum / nData_count;
    			ucThre = ucThre_new;
    			ucThre_new = (nBack_sum + nData_sum) / 2;
    		}
    		// 二值化处理
    		int nBlack = 0;
    		int nWhite = 0;
    		for (j = 0; j < height; ++j) {
    			for (i = 0; i < width; ++i) {
    				nValue = (int) mat.get(j, i)[0];
    				if (nValue > ucThre_new) {
    					mat.put(j, i, WHITE);
    					nWhite++;
    				} else {
    					mat.put(j, i, BLACK);
    					nBlack++;
    				}
    			}
    		}
    		// 确保白底黑字
    		if (nBlack > nWhite) {
    			for (j = 0; j < height; ++j) {
    				for (i = 0; i < width; ++i) {
    					nValue = (int) (mat.get(j, i)[0]);
    					if (nValue == 0) {
    						mat.put(j, i, WHITE);
    					} else {
    						mat.put(j, i, BLACK);
    					}
    				}
    			}
    		}
    	}
    	// 延时加载
    	private static WebElement waitWebElement(WebDriver driver, By by, int count) throws Exception {
    		WebElement webElement = null;
    		boolean isWait = false;
    		for (int k = 0; k < count; k++) {
    			try {
    				webElement = driver.findElement(by);
    				if (isWait)
    					System.out.println(" ok!");
    				return webElement;
    			} catch (org.openqa.selenium.NoSuchElementException ex) {
    				isWait = true;
    				if (k == 0)
    					System.out.print("waitWebElement(" + by.toString() + ")");
    				else
    					System.out.print(".");
    				Thread.sleep(50);
    			}
    		}
    		if (isWait)
    			System.out.println(" outTime!");
    		return null;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216

    在这里插入图片描述
    戳这里→康康你手机号在过多少网站注册过!!!
    友情推荐:新一代安全短信

    相关阅读
    谷歌图形验证码在AI 面前已经形同虚设,所以谷歌宣布退出验证码服务, 那么当所有的图形验证码都被破解时
    《腾讯防水墙滑动拼图验证码》
    《百度旋转图片验证码》
    《网易易盾滑动拼图验证码》
    《顶象区域面积点选验证码》
    《顶象滑动拼图验证码》
    《极验滑动拼图验证码》
    《使用深度学习来破解 captcha 验证码》
    《验证码终结者-基于CNN+BLSTM+CTC的训练部署套件》

  • 相关阅读:
    MyBatis-plus超神用法--一文带你玩转MP
    流媒体传输 - RTSP 协议报文分析
    Spring Cloud Stream 消息驱动基础入门与实践总结
    python中的range函数|python中的range函数|range()函数详解|Python中range(len())的用法
    计算机网络:随机访问介质访问控制之令牌传递协议
    阿里面试官问的 Redis 太刁钻,索性整理出所有大厂的 Redis 面试题,拿下麻烦的面试官
    最好的期货开户的标准是什么?
    计算机毕业设计Java海康物流(源码+系统+mysql数据库+lw文档)
    ERP企业管理系统报价?购买一套ERP需要多少钱?
    水晶球,构造回文(关键词-字符串)
  • 原文地址:https://blog.csdn.net/weixin_44549063/article/details/126371717