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
注意事项
- 选择器准确性:确保 CSS 选择器与目标网页的实际元素匹配
- 等待时间:根据网页加载速度调整等待时间
- 错误处理:在生产环境中添加适当的错误处理
- 反爬虫检测:某些网站可能会检测自动化行为
- Cookie 安全:妥善保存和管理 Cookie 文件
总结
通过 headless_chrome
crate,我们可以在 Rust 中轻松实现浏览器自动化操作。这个库提供了丰富的 API 来控制浏览器行为,非常适合构建网页抓取、自动化测试和数据收集工具。
祺洛管理系统介绍
祺洛是一个 Rust 企业级快速开发平台,基于(Rust、 Axum、Sea-orm、Jwt、Vue),内置模块如:部门管理、角色用户、菜单及按钮授权、数据权限、系统参数、日志管理等。在线定时任务配置;支持集群,支持多数据源,支持分布式部署。
🌐 官方网站: https://www.qiluo.vip/
让企业级应用开发更简单、更高效、更安全