使用Dart实现极验滑动验证码识别


本文将展示如何使用Dart语言实现极验滑动验证码的自动识别。从模拟点击到识别滑动缺口、计算位移并模拟拖动滑块。如果认证失败,则重复调用直到成功。

识别思路
模拟点击切换为滑动验证,并显示验证界面。
识别滑动缺口的位置,计算位移。
模拟拖动滑块。
若认证失败,重复调用。
详细过程及代码
初始化
首先,初始化Selenium WebDriver对象并配置参数。极验验证码测试页面的网址如下:更多内容联系1436423940

dart

import 'dart:async';
import 'dart:convert';
import 'dart:typed_data';
import 'package:image/image.dart' as img;
import 'package:webdriver/io.dart';

const String url = 'https://www.geetest.com/type/';

class CrackGeetest {
  WebDriver driver;

  CrackGeetest(this.driver);

  Future<void> open() async {
    await driver.get(url);
  }

  Future<void> close() async {
    await driver.quit();
  }
}

Future<void> main() async {
  WebDriver driver = await createDriver(
    uri: Uri.parse('http://localhost:4444/wd/hub'),
    desired: {'browserName': 'chrome'},
  );

  CrackGeetest crackGeetest = CrackGeetest(driver);
  await crackGeetest.open();
  await crackGeetest.crack();
  await crackGeetest.close();
}

extension on CrackGeetest {
  Future<void> crack() async {
    try {
      await changeToSlide();
      await getGeetestButton();
      await waitPic();
      var slider = await getSlider();
      var image1 = await getGeetestImage('captcha1.png');
      await deleteStyle();
      var image2 = await getGeetestImage('captcha2.png');
      var gap = getGap(image1, image2);
      print('缺口位置: $gap');
      gap -= 6;
      var track = getTrack(gap);
      await moveToGap(slider, track);
      var success = await waitUntil(
          By.className('geetest_success_radar_tip_content'), '验证成功');
      if (success) {
        print('验证成功');
      } else {
        print('Failed-Retry');
        await crack();
      }
    } catch (e) {
      print('Failed-Retry: $e');
      await crack();
    }
  }

  Future<void> changeToSlide() async {
    var huadong = await driver.findElement(
        const By.cssSelector('.products-content ul > li:nth-child(2)'));
    await huadong.click();
  }

  Future<void> getGeetestButton() async {
    var button = await driver.findElement(const By.cssSelector('.geetest_radar_tip'));
    await button.click();
  }

  Future<void> waitPic() async {
    await driver.findElement(const By.cssSelector('.geetest_popup_wrap'));
  }

  Future<WebElement> getSlider() async {
    return await driver.findElement(const By.className('geetest_slider_button'));
  }

  Future<Uint8List> getGeetestImage(String name) async {
    var screenshot = await driver.captureScreenshotAsList();
    var file = File(name);
    await file.writeAsBytes(screenshot);
    return Uint8List.fromList(screenshot);
  }

  Future<void> deleteStyle() async {
    await driver.execute('document.querySelectorAll("canvas")[2].style=""', []);
  }

  int getGap(Uint8List img1Bytes, Uint8List img2Bytes) {
    var img1 = img.decodeImage(img1Bytes);
    var img2 = img.decodeImage(img2Bytes);
    int left = 60;
    for (var i = left; i < img1!.width; i++) {
      for (var j = 0; j < img1.height; j++) {
        if (!isPixelEqual(img1.getPixel(i, j), img2!.getPixel(i, j))) {
          return i;
        }
      }
    }
    return left;
  }

  bool isPixelEqual(int pixel1, int pixel2) {
    var threshold = 60;
    var r1 = img.getRed(pixel1);
    var g1 = img.getGreen(pixel1);
    var b1 = img.getBlue(pixel1);
    var r2 = img.getRed(pixel2);
    var g2 = img.getGreen(pixel2);
    var b2 = img.getBlue(pixel2);

    return (r1 - r2).abs() < threshold &&
        (g1 - g2).abs() < threshold &&
        (b1 - b2).abs() < threshold;
  }

  List<int> getTrack(int distance) {
    var track = <int>[];
    var current = 0;
    var mid = (distance * 3 / 5).round();
    var t = 0.2;
    var v = 0.0;
    distance += 14;
    while (current < distance) {
      var a = current < mid ? 2.0 : -1.5;
      var v0 = v;
      v = v0 + a * t;
      var move = (v0 * t + 0.5 * a * t * t).round();
      current += move;
      track.add(move);
    }
    return track;
  }

  Future<void> moveToGap(WebElement slider, List<int> track) async {
    await slider.clickAndHold();
    for (var x in track) {
      await driver.mouseMoveTo(slider, xOffset: x, yOffset: 0);
      await Future.delayed(Duration(milliseconds: 50));
    }
    await slider.release();
  }

  Future<bool> waitUntil(By by, String text) async {
    try {
      var element = await driver.findElement(by);
      var elementText = await element.text;
      return elementText.contains(text);
    } catch (_) {
      return false;
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值