使用Rust和Selenium破解网易易盾滑动验证码


准备工作
安装Rust和相关库
首先,你需要安装Rust编译器。如果你还没有安装,可以访问Rust官网进行安装。

接下来,我们需要安装Rust的Selenium客户端库fantoccini和OpenCV的Rust绑定库opencv。

在Cargo.toml中添加依赖:


[dependencies]
fantoccini = "0.15"
opencv = { version = "0.52", features = ["contrib", "opencv-4"] }
验证码页面
验证码页面地址:https://dun.163.com/trial/jigsaw

代码实现
1. 初始化Selenium
我们首先启动Selenium WebDriver并导航到验证码页面。

rust
复制代码
use fantoccini::{Client, Locator};
use std::time::Duration;
use tokio;

#[tokio::main]
async fn main() -> Result<(), fantoccini::error::CmdError> {
    let mut caps = serde_json::map::Map::new();
    caps.insert("browserName".to_string(), serde_json::Value::String("chrome".to_string()));

    let c = Client::with_capabilities("http://localhost:4444", caps).await?;
    c.goto("https://dun.163.com/trial/jigsaw").await?;
    tokio::time::sleep(Duration::from_secs(3)).await;

    // 后续的验证码处理代码将放在这里

    c.close().await
}
2. 获取验证码图片
获取验证码图片并保存到本地,以便使用OpenCV进行图像处理。

rust

use std::fs::File;
use std::io::Write;

async fn get_image(c: &Client, selector: Locator, file_path: &str) -> Result<(), fantoccini::error::CmdError> {
    let elem = c.find(selector).await?;
    let img_url = elem.attr("src").await?.unwrap();
    let resp = reqwest::get(&img_url).await?.bytes().await?;

    let mut file = File::create(file_path)?;
    file.write_all(&resp)?;

    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut caps = serde_json::map::Map::new();
    caps.insert("browserName".to_string(), serde_json::Value::String("chrome".to_string()));

    let c = Client::with_capabilities("http://localhost:4444", caps).await?;
    c.goto("https://dun.163.com/trial/jigsaw").await?;
    tokio::time::sleep(Duration::from_secs(3)).await;

    get_image(&c, Locator::Css(".yidun_bg-img"), "bg.png").await?;
    get_image(&c, Locator::Css(".yidun_jigsaw"), "puzzle.png").await?;

    // 后续的验证码处理代码将放在这里

    c.close().await?;

    Ok(())
}
3. 使用OpenCV匹配图像
使用OpenCV找到拼图缺口的位置。

rust

use opencv::{
    core::{Point, Scalar, Size},
    imgcodecs::{imread, imwrite, IMREAD_COLOR},
    imgproc::{match_template, TM_CCOEFF_NORMED},
    prelude::*,
};

fn get_slide_distance() -> Result<f64, Box<dyn std::error::Error>> {
    let bg_image = imread("bg.png", IMREAD_COLOR)?;
    if bg_image.empty() {
        return Err("Error reading background image".into());
    }

    let puzzle_image = imread("puzzle.png", IMREAD_COLOR)?;
    if puzzle_image.empty() {
        return Err("Error reading puzzle image".into());
    }

    let mut result = Mat::default();
    match_template(&bg_image, &puzzle_image, &mut result, TM_CCOEFF_NORMED, &Mat::default())?;

    let min_max_loc = core::min_max_loc(&result, None, None, None, None)?;
    let match_location = min_max_loc.max_loc;

    Ok(match_location.x)
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut caps = serde_json::map::Map::new();
    caps.insert("browserName".to_string(), serde_json::Value::String("chrome".to_string()));

    let c = Client::with_capabilities("http://localhost:4444", caps).await?;
    c.goto("https://dun.163.com/trial/jigsaw").await?;
    tokio::time::sleep(Duration::from_secs(3)).await;

    get_image(&c, Locator::Css(".yidun_bg-img"), "bg.png").await?;
    get_image(&c, Locator::Css(".yidun_jigsaw"), "puzzle.png").await?;

    let distance = get_slide_distance()?;
    println!("Slide distance: {}", distance);

    // 后续的验证码处理代码将放在这里

    c.close().await?;

    Ok(())
}
4. 模拟滑动行为
模拟人类滑动行为,以避免被检测为机器人。

rust

use rand::Rng;

async fn slide_puzzle(c: &Client, distance: f64) -> Result<(), fantoccini::error::CmdError> {
    let slider = c.find(Locator::Css(".yidun_slider")).await?;
    let rect = slider.rect().await?;
    let start_x = rect.x + rect.width / 2;
    let start_y = rect.y + rect.height / 2;

    let mut actions = c.action_chain();
    actions = actions.move_to_element_center(&slider).click_and_hold();

    let steps = 30;
    let move_x = distance / steps as f64;

    for i in 0..steps {
        let current_x = start_x + (move_x * i as f64) as i32;
        actions = actions.move_by_offset(current_x - start_x, 0);
        tokio::time::sleep(Duration::from_millis(100 + rand::thread_rng().gen_range(0..50))).await;
    }

    actions.release().perform().await?;
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut caps = serde_json::map::Map::new();
    caps.insert("browserName".to_string(), serde_json::Value::String("chrome".to_string()));

    let c = Client::with_capabilities("http://localhost:4444", caps).await?;
    c.goto("https://dun.163.com/trial/jigsaw").await?;
    tokio::time::sleep(Duration::from_secs(3)).await;

    get_image(&c, Locator::Css(".yidun_bg-img"), "bg.png").await?;
    get_image(&c, Locator::Css(".yidun_jigsaw"), "puzzle.png").await?;

    let distance = get_slide_distance()?;
    println!("Slide distance: {}", distance);

    slide_puzzle(&c, distance).await?;

    tokio::time::sleep(Duration::from_secs(5)).await;

    c.close().await?;

    Ok(())
}

  • 17
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值