使用D语言破解极验滑动验证码


本文将介绍如何使用D语言和Selenium WebDriver来破解极验滑动验证码。我们将详细介绍每一步的实现过程,包括模拟点击、识别滑动缺口、计算位移以及模拟拖动滑块。

识别流程
打开网页并切换为滑动验证模式。
识别滑动缺口的位置,计算位移。
模拟拖动滑块。
若认证失败,重复调用。
实现步骤与代码
初始化
首先,初始化Selenium WebDriver对象并配置参数。极验验证码测试页面的网址如下:

d

import std.stdio;
import std.net.curl;
import std.json;
import std.conv;
import std.algorithm;
import std.range;
import std.string;
import std.exception;
import std.array;
import std.file;
import std.process;
import std.parallelism;

import selenium.webdriver;
import selenium.elements;
import selenium.common.by;
import selenium.support.ui;
import core.time;

enum URL = "https://www.geetest.com/type/";
enum BORDER = 6;

class CrackGeetest {
    WebDriver driver;
    WebDriverWait wait;

    this() {
        driver = new ChromeDriver();
        wait = new WebDriverWait(driver, 10.seconds);
    }

    void open() {
        driver.get(URL);
    }

    void close() {
        driver.quit();
    }

    WebElement changeToSlide() { 更多内容联系1436423940
        return wait.until(elementToBeClickable(By.cssSelector(".products-content ul > li:nth-child(2)")));
    }

    WebElement getGeetestButton() {
        return wait.until(elementToBeClickable(By.cssSelector(".geetest_radar_tip")));
    }

    void waitPic() {
        wait.until(presenceOfElementLocated(By.cssSelector(".geetest_popup_wrap")));
    }

    string getScreenshot() {
        string screenshot = driver.getScreenshotAs(Base64);
        return screenshot;
    }

    (int, int, int, int) getPosition() {
        auto img = wait.until(presenceOfElementLocated(By.className("geetest_canvas_img")));
        Thread.sleep(2.seconds);
        auto location = img.location;
        auto size = img.size;
        return (location.y, location.y + size.height, location.x, location.x + size.width);
    }

    WebElement getSlider() {
        return wait.until(elementToBeClickable(By.className("geetest_slider_button")));
    }

    void saveImage(string base64, string fileName) {
        auto bytes = base64.decodeBase64;
        write(fileName, bytes);
    }

    void getGeetestImage(string name) {
        auto (top, bottom, left, right) = getPosition();
        writeln("验证码位置: ", top, bottom, left, right);
        auto screenshot = getScreenshot();
        saveImage(screenshot, name);
    }

    void deleteStyle() {
        driver.executeScript("document.querySelectorAll('canvas')[2].style=''");
    }

    bool isPixelEqual(string img1, string img2, int x, int y) {
        auto cmd = `compare -metric AE -subimage-search -dissimilarity-threshold 0.1 ` ~ img1 ~ ` ` ~ img2 ~ ` diff.png`;
        auto result = executeShell(cmd);
        return result.status == 0;
    }

    int getGap(string img1, string img2) {
        int left = 60;
        foreach (i; left .. img1.length) {
            foreach (j; 0 .. img1.length) {
                if (!isPixelEqual(img1, img2, i, j)) {
                    return i;
                }
            }
        }
        return left;
    }

    int[] getTrack(int distance) {
        int[] track;
        int current = 0;
        int mid = distance * 3 / 5;
        double t = 0.2;
        int v = 0;
        distance += 14;
        while (current < distance) {
            int a = (current < mid) ? 2 : -1.5;
            int v0 = v;
            v = v0 + cast(int)(a * t);
            int move = cast(int)(v0 * t + 0.5 * a * t * t);
            current += move;
            track ~= move;
        }
        return track;
    }

    void moveToGap(WebElement slider, int[] tracks) {
        driver.actions().clickAndHold(slider).perform();
        foreach (move; tracks) {
            driver.actions().moveByOffset(move, 0).perform();
        }
        foreach (move; [-1, -1, -2, -2, -3, -2, -2, -1, -1]) {
            driver.actions().moveByOffset(move, 0).perform();
        }
        shakeMouse();
        Thread.sleep(500.msecs);
        driver.actions().release().perform();
    }

    void shakeMouse() {
        driver.actions().moveByOffset(-3, 0).perform();
        driver.actions().moveByOffset(2, 0).perform();
    }

    void crack() {
        open();
        changeToSlide().click();
        getGeetestButton().click();
        waitPic();
        auto slider = getSlider();
        getGeetestImage("captcha1.png");
        deleteStyle();
        getGeetestImage("captcha2.png");
        int gap = getGap("captcha1.png", "captcha2.png") - BORDER;
        auto track = getTrack(gap);
        moveToGap(slider, track);
        auto success = wait.until(textToBePresentInElementLocated(By.className("geetest_success_radar_tip_content"), "验证成功"));
        if (success) {
            writeln("验证成功");
        } else {
            writeln("验证失败,重试中...");
            crack();
        }
        close();
    }
}

void main() {
    auto crack = new CrackGeetest();
    crack.crack();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值