使用selenium + OpenCV破解腾讯防水墙滑动验证码

发表于:2021-5-13 09:22

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:香芋味的猫    来源:CSDN

  产品样例
  注意!!!
  在模拟滑动时不能按照相同速度或者过快的速度滑动,需要向人滑动时一样先快后慢,这样才不容易被识别。
  模拟滑动代码↓↓↓
  /**
   * 模拟人工移动
   * @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;
  }
  看操作,no bb,直接上代码:
  private final String INDEX_URL = "https://007.qq.com/online.html?ADTAG=index.head";
  private void seleniumTest() {
  ChromeDriverManager manager = ChromeDriverManager.getInstance();
  int status = -1;
  try {
  WebDriver driver = manager.getDriver();
  driver.get(INDEX_URL);
  driver.manage().window().maximize(); // 设置浏览器窗口最大化
  Thread.sleep(10000);
  driver.findElement(By.className("wp-onb-tit")).findElements(By.tagName("a")).get(1).click();
  Thread.sleep(500);
  // 点击出现滑动图
  waitWebElement(driver, By.id("code"), 500).click();
  Thread.sleep(100);
  // 获取到验证区域
  driver.switchTo().frame(waitWebElement(driver, By.id("tcaptcha_iframe"), 500));
  Thread.sleep(100);
  // 获取滑动按钮
  WebElement moveElemet = waitWebElement(driver, By.id("tcaptcha_drag_button"), 500);
  Thread.sleep(100);
  // 获取带阴影的背景图
  String bgUrl = waitWebElement(driver, By.id("slideBg"), 500).getAttribute("src");
  Thread.sleep(100);
  // 获取带阴影的小图
  String sUrl = waitWebElement(driver, By.id("slideBlock"), 500).getAttribute("src");
  Thread.sleep(100);
  // 获取高度
  String topStr = waitWebElement(driver, By.id("slideBlock"), 500).getAttribute("style").substring(32, 36);
  int top = Integer.parseInt(topStr.substring(0, topStr.indexOf("p"))) * 2;
  Thread.sleep(100);
  // 计算移动距离
  int distance = (int) Double.parseDouble(getTencentDistance(bgUrl, sUrl, top));
  // 滑动
  move(driver, moveElemet, distance);
  Thread.sleep(5000);
  } catch (Exception e) {
  e.printStackTrace();
  } finally {
  manager.closeDriver(status);
  }
  }
  /**
   * 获取腾讯验证滑动距离
   * 
   * @return
   */
  public static String dllPath = "C://chrome//opencv_java440.dll";
  public String getTencentDistance(String bUrl, String sUrl, int top) {
  System.load(dllPath);
  File bFile = new File("C:/qq_b.jpg");
  File sFile = new File("C:/qq_s.jpg");
  try {
  FileUtils.copyURLToFile(new URL(bUrl), bFile);
  FileUtils.copyURLToFile(new URL(sUrl), sFile);
  BufferedImage bgBI = ImageIO.read(bFile);
  BufferedImage sBI = ImageIO.read(sFile);
  // 裁剪
  bgBI = bgBI.getSubimage(360, top, bgBI.getWidth() - 370, sBI.getHeight());
  ImageIO.write(bgBI, "png", bFile);
  Mat s_mat = Imgcodecs.imread(sFile.getPath());
  Mat b_mat = Imgcodecs.imread(bFile.getPath());
  // 转灰度图像
  Mat s_newMat = new Mat();
  Imgproc.cvtColor(s_mat, s_newMat, Imgproc.COLOR_BGR2GRAY);
  // 二值化图像
  binaryzation(s_newMat);
  Imgcodecs.imwrite(sFile.getPath(), s_newMat);
  int result_rows = b_mat.rows() - s_mat.rows() + 1;
  int result_cols = b_mat.cols() - s_mat.cols() + 1;
  Mat g_result = new Mat(result_rows, result_cols, CvType.CV_32FC1);
  Imgproc.matchTemplate(b_mat, s_mat, g_result, Imgproc.TM_SQDIFF); // 归一化平方差匹配法
  // 归一化相关匹配法
  Core.normalize(g_result, g_result, 0, 1, Core.NORM_MINMAX, -1, new Mat());
  Point matchLocation = new Point();
  MinMaxLocResult mmlr = Core.minMaxLoc(g_result);
  matchLocation = mmlr.maxLoc; // 此处使用maxLoc还是minLoc取决于使用的匹配算法
  Imgproc.rectangle(b_mat, matchLocation,
  new Point(matchLocation.x + s_mat.cols(), matchLocation.y + s_mat.rows()), new Scalar(0, 0, 0, 0));
  return "" + ((matchLocation.x + s_mat.cols() + 360 - sBI.getWidth() - 46) / 2);
  } catch (Throwable e) {
  e.printStackTrace();
  return null;
  } finally {
  bFile.delete();
  sFile.delete();
  }
  }
  /**
   * 
   * @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;
  }

      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号