Rust 使用 Headless Chrome 入门指南

#代码星辉·七月创作之星挑战赛#

Rust 使用 Headless Chrome 入门指南

简介

在 Rust 中使用 Headless Chrome 可以实现网页自动化操作,包括模拟用户交互、数据抓取、自动化测试等。本文将介绍如何使用 headless_chrome crate 来控制浏览器,包括模拟登录和 Cookie 管理。

环境准备

1. 安装 Chrome 浏览器

确保系统已安装 Chrome 浏览器:

# Ubuntu/Debian
sudo apt update
sudo apt install google-chrome-stable

# macOS (使用 Homebrew)
brew install --cask google-chrome

2. 创建 Rust 项目

cargo new headless_chrome_demo
cd headless_chrome_demo

3. 添加依赖

Cargo.toml 中添加所需依赖:

[dependencies]
headless_chrome = "1.0"
tokio = { version = "1.0", features = ["full"] }
serde_json = "1.0"
anyhow = "1.0"

基础使用示例

1. 创建浏览器实例

use headless_chrome::{Browser, LaunchOptions};
use anyhow::Result;

fn main() -> Result<()> {
    // 启动浏览器
    let browser = Browser::new(
        LaunchOptions::default_builder()
            .headless(true)  // 设置为无头模式
            .sandbox(false)  // 禁用沙箱
            .build()
            .expect("Could not find chrome-executable"),
    )?;

    // 创建新标签页
    let tab = browser.new_tab()?;

    // 导航到网页
    tab.navigate_to("https://example.com")?;

    // 等待页面加载
    tab.wait_until_navigated()?;

    println!("页面标题: {}", tab.get_title()?);

    Ok(())
}

2. 网页截图

use headless_chrome::{Browser, LaunchOptions};
use anyhow::Result;

fn take_screenshot() -> Result<()> {
    let browser = Browser::new(LaunchOptions::default())?;
    let tab = browser.new_tab()?;
    
    tab.navigate_to("https://example.com")?;
    tab.wait_until_navigated()?;
    
    // 截图
    let png_data = tab.capture_screenshot(
        headless_chrome::protocol::cdp::Page::CaptureScreenshotFormatOption::Png,
        None,
        None,
        true,
    )?;
    
    // 保存截图
    std::fs::write("screenshot.png", png_data)?;
    println!("截图已保存到 screenshot.png");
    
    Ok(())
}

模拟登录示例

以下是一个完整的登录示例,包括输入用户名、密码、点击登录按钮和保存 Cookie:

use headless_chrome::{Browser, LaunchOptions};
use headless_chrome::protocol::cdp::Network;
use anyhow::Result;
use std::time::Duration;
use serde_json::Value;

fn simulate_login() -> Result<()> {
    // 启动浏览器
    let browser = Browser::new(
        LaunchOptions::default_builder()
            .headless(true)
            .window_size(Some((1920, 1080)))
            .build()
            .expect("Could not find chrome-executable"),
    )?;

    let tab = browser.new_tab()?;
    
    // 启用网络域以便获取 Cookie
    tab.enable_network()?;
    
    // 导航到登录页面
    println!("正在导航到登录页面...");
    tab.navigate_to("https://example.com/login")?;
    tab.wait_until_navigated()?;
    
    // 等待页面完全加载
    std::thread::sleep(Duration::from_secs(2));
    
    // 查找并填写用户名
    println!("填写用户名...");
    let username_selector = "input[name='username']"; // 根据实际页面调整选择器
    tab.wait_for_element(username_selector)?
        .click()?
        .type_into("your_username")?;
    
    // 查找并填写密码
    println!("填写密码...");
    let password_selector = "input[name='password']"; // 根据实际页面调整选择器
    tab.wait_for_element(password_selector)?
        .click()?
        .type_into("your_password")?;
    
    // 点击登录按钮
    println!("点击登录按钮...");
    let login_button_selector = "button[type='submit']"; // 根据实际页面调整选择器
    tab.wait_for_element(login_button_selector)?
        .click()?;
    
    // 等待登录完成(可以通过 URL 变化或特定元素出现来判断)
    std::thread::sleep(Duration::from_secs(3));
    
    // 获取所有 Cookie
    println!("获取 Cookie...");
    let cookies = tab.get_cookies()?;
    
    // 保存 Cookie 到文件
    save_cookies_to_file(&cookies)?;
    
    println!("登录完成,Cookie 已保存!");
    
    Ok(())
}

// 保存 Cookie 到 JSON 文件
fn save_cookies_to_file(cookies: &[Network::Cookie]) -> Result<()> {
    let cookies_json = serde_json::to_string_pretty(cookies)?;
    std::fs::write("cookies.json", cookies_json)?;
    println!("Cookie 已保存到 cookies.json");
    Ok(())
}

// 从文件加载 Cookie
fn load_cookies_from_file() -> Result<Vec<Network::Cookie>> {
    let cookies_data = std::fs::read_to_string("cookies.json")?;
    let cookies: Vec<Network::Cookie> = serde_json::from_str(&cookies_data)?;
    Ok(cookies)
}

// 使用已保存的 Cookie 访问需要登录的页面
fn access_with_saved_cookies() -> Result<()> {
    let browser = Browser::new(LaunchOptions::default())?;
    let tab = browser.new_tab()?;
    
    tab.enable_network()?;
    
    // 先导航到目标域名
    tab.navigate_to("https://example.com")?;
    tab.wait_until_navigated()?;
    
    // 加载保存的 Cookie
    let cookies = load_cookies_from_file()?;
    
    // 设置 Cookie
    for cookie in cookies {
        tab.set_cookie(cookie)?;
    }
    
    // 刷新页面以应用 Cookie
    tab.reload(false, None)?;
    tab.wait_until_navigated()?;
    
    println!("使用保存的 Cookie 访问页面成功!");
    
    Ok(())
}

高级用法

1. 等待特定元素出现

use std::time::Duration;

fn wait_for_element_example() -> Result<()> {
    let browser = Browser::new(LaunchOptions::default())?;
    let tab = browser.new_tab()?;
    
    tab.navigate_to("https://example.com")?;
    
    // 等待特定元素出现(最多等待 10 秒)
    let element = tab.wait_for_element_with_timeout(".loading-complete", Duration::from_secs(10))?;
    
    println!("元素已出现: {}", element.get_description()?.node_name);
    
    Ok(())
}

2. 执行 JavaScript

fn execute_javascript() -> Result<()> {
    let browser = Browser::new(LaunchOptions::default())?;
    let tab = browser.new_tab()?;
    
    tab.navigate_to("https://example.com")?;
    tab.wait_until_navigated()?;
    
    // 执行 JavaScript 代码
    let result = tab.evaluate("document.title", false)?;
    
    if let Some(value) = result.value {
        println!("页面标题: {:?}", value);
    }
    
    // 修改页面内容
    tab.evaluate(
        "document.body.style.backgroundColor = 'red';",
        false
    )?;
    
    Ok(())
}

3. 处理表单和下拉菜单

fn handle_forms() -> Result<()> {
    let browser = Browser::new(LaunchOptions::default())?;
    let tab = browser.new_tab()?;
    
    tab.navigate_to("https://example.com/form")?;
    tab.wait_until_navigated()?;
    
    // 选择下拉菜单选项
    tab.wait_for_element("select[name='country']")?
        .click()?;
    
    tab.wait_for_element("option[value='US']")?
        .click()?;
    
    // 勾选复选框
    tab.wait_for_element("input[type='checkbox'][name='agree']")?
        .click()?;
    
    // 选择单选按钮
    tab.wait_for_element("input[type='radio'][value='option1']")?
        .click()?;
    
    Ok(())
}

完整的 main.rs 示例

use headless_chrome::{Browser, LaunchOptions};
use headless_chrome::protocol::cdp::Network;
use anyhow::Result;
use std::time::Duration;

fn main() -> Result<()> {
    println!("=== Headless Chrome 登录示例 ===");
    
    // 模拟登录
    if let Err(e) = simulate_login() {
        eprintln!("登录失败: {}", e);
        return Err(e);
    }
    
    // 使用保存的 Cookie 访问页面
    println!("\n=== 使用保存的 Cookie 访问页面 ===");
    if let Err(e) = access_with_saved_cookies() {
        eprintln!("使用 Cookie 访问失败: {}", e);
    }
    
    Ok(())
}

// ... (包含前面定义的所有函数)

运行项目

cargo run

注意事项

  1. 选择器准确性:确保 CSS 选择器与目标网页的实际元素匹配
  2. 等待时间:根据网页加载速度调整等待时间
  3. 错误处理:在生产环境中添加适当的错误处理
  4. 反爬虫检测:某些网站可能会检测自动化行为
  5. Cookie 安全:妥善保存和管理 Cookie 文件

总结

通过 headless_chrome crate,我们可以在 Rust 中轻松实现浏览器自动化操作。这个库提供了丰富的 API 来控制浏览器行为,非常适合构建网页抓取、自动化测试和数据收集工具。

祺洛管理系统介绍

祺洛是一个 Rust 企业级快速开发平台,基于(Rust、 Axum、Sea-orm、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理等。在线定时任务配置;支持集群,支持多数据源,支持分布式部署。
🌐 官方网站: https://www.qiluo.vip/
让企业级应用开发更简单、更高效、更安全

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

will_csdn_go

每一行代码都是思维的体现

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值