Rust浏览器自动化库chromiumoxide的使用,通过Rust控制Chromium实现高效网页爬取与自动化测试

Rust浏览器自动化库chromiumoxide的使用,通过Rust控制Chromium实现高效网页爬取与自动化测试

chromiumoxide 提供了一个高级的异步API来控制Chrome或Chromium浏览器,通过DevTools协议进行通信。它支持所有类型的Chrome DevTools协议,可以启动无头(headless)或有头的Chromium实例,也可以连接到正在运行的实例。

使用方法

以下是使用chromiumoxide进行网页自动化操作的完整示例:

use futures::StreamExt;
use chromiumoxide::browser::{Browser, BrowserConfig};

#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 创建一个带有UI的浏览器实例(默认是无头模式)
    let (mut browser, mut handler) =
        Browser::launch(BrowserConfig::builder().with_head().build()?).await?;
    
    // 创建一个新任务来持续轮询处理程序
    let handle = async_std::task::spawn(async move {
        while let Some(h) = handler.next().await {
            if h.is_err() {
                break;
            }
        }
    });
    
    // 创建一个新页面并导航到URL
    let page = browser.new_page("https://en.wikipedia.org").await?;
    
    // 查找搜索框,输入内容并按下Enter键
    page.find_element("input#searchInput")
        .await?
        .click()
        .await?
        .type_str("Rust programming language")
        .await?
        .press_key("Enter")
        .await?;

    // 等待导航完成并获取页面内容
    let html = page.wait_for_navigation().await?.content().await?;
    
    browser.close().await?;
    handle.await;
    Ok(())
}

完整示例

下面是一个更完整的示例,展示如何使用chromiumoxide进行网页爬取和自动化测试:

use futures::StreamExt;
use chromiumoxide::browser::{Browser, BrowserConfig};
use chromiumoxide::page::PrintToPdfParams;

#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置浏览器选项 - 无头模式,窗口大小等
    let config = BrowserConfig::builder()
        .with_head()  // 显示UI界面
        .with_window_size(1280, 720)
        .build()?;
    
    // 启动浏览器
    let (mut browser, mut handler) = Browser::launch(config).await?;
    
    // 处理浏览器事件的任务
    let handle = async_std::task::spawn(async move {
        while let Some(h) = handler.next().await {
            if h.is_err() {
                break;
            }
        }
    });
    
    // 创建新页面
    let page = browser.new_page("https://example.com").await?;
    
    // 截图功能
    page.screenshot(chromiumoxide::page::ScreenshotParams::builder()
        .with_full_page(true)
        .build()?)
        .await?
        .save("example_screenshot.png")
        .await?;
    
    // 生成PDF
    let pdf_params = PrintToPdfParams::builder()
        .with_landscape(false)
        .with_display_header_footer(false)
        .build()?;
    let pdf_data = page.pdf(pdf_params).await?;
    async_std::fs::write("example.pdf", pdf_data).await?;
    
    // 表单自动化
    page.find_element("input[name='username']")
        .await?
        .type_str("testuser")
        .await?;
    
    page.find_element("input[name='password']")
        .await?
        .type_str("password123")
        .await?;
    
    page.find_element("button[type='submit']")
        .await?
        .click()
        .await?;
    
    // 等待特定元素出现
    let success_element = page.wait_for_element(".success-message").await?;
    let success_text = success_element.inner_text().await?;
    println!("Success message: {}", success_text);
    
    // 获取页面所有链接
    let links = page.find_elements("a").await?;
    for link in links {
        let href = link.attribute("href").await?;
        let text = link.inner_text().await?;
        println!("Link: {} - {}", text, href.unwrap_or_default());
    }
    
    // 关闭浏览器
    browser.close().await?;
    handle.await;
    Ok(())
}

添加到项目

chromiumoxide支持async-std和tokio运行时。默认配置使用async-std:

chromiumoxide = { git = "https://github.com/mattsse/chromiumoxide", branch = "main"}

要使用tokio运行时:

chromiumoxide = { git = "https://github.com/mattsse/chromiumoxide", features = ["tokio-runtime"], default-features = false, branch = "main"}

常见问题

Q: 一个新的chromium实例被启动但随后超时。

A: 检查你的chromium语言设置是否为英语。chromiumoxide尝试从chromium进程输出中解析调试端口,这仅限于英语。

chromiumoxide提供了强大的浏览器自动化功能,非常适合网页爬取和自动化测试场景。通过其丰富的API,开发者可以轻松实现复杂的浏览器交互操作。


1 回复

Rust浏览器自动化库chromiumoxide使用指南

概述

chromiumoxide是一个基于Rust的浏览器自动化库,它允许开发者通过Rust代码控制Chromium浏览器,实现网页爬取和自动化测试功能。这个库提供了与Chrome DevTools Protocol的交互能力,类似于Python中的Pyppeteer或Selenium。

主要特性

  • 完全异步支持(基于tokio)
  • 支持页面导航、表单填写、点击等操作
  • 支持JavaScript执行
  • 支持网络请求拦截和修改
  • 支持截图和PDF生成
  • 轻量级且性能高效

安装方法

在Cargo.toml中添加依赖:

[dependencies]
chromiumoxide = "0.7"
tokio = { version = "1.0", features = ["full"] }

基本使用方法

1. 启动浏览器实例

use chromiumoxide::browser::{Browser, BrowserConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 配置浏览器
    let (browser, mut handler) = Browser::launch(
        BrowserConfig::builder()
            .with_head()  // 无头模式
            .build()?
    ).await?;
    
    // 处理浏览器事件的任务
    let handle = tokio::task::spawn(async move {
        while let Some(h) = handler.next().await {
            if h.is_err() {
                break;
            }
        }
    });

    // 创建新页面
    let page = browser.new_page("https://example.com").await?;
    
    // 等待页面加载完成
    page.wait_for_navigation().await?;
    
    // 其他操作...
    
    // 关闭浏览器
    browser.close().await?;
    handle.await?;
    Ok(())
}

2. 页面导航与内容获取

// 导航到页面
page.goto("https://www.rust-lang.org").await?;

// 获取页面标题
let title = page.evaluate("document.title").await?;
println!("页面标题: {:?}", title);

// 获取页面HTML内容
let content = page.content().await?;
println!("页面内容: {}", content);

3. 元素交互操作

// 点击元素
page.find_element("button#submit").await?.click().await?;

// 填写表单
page.find_element("input#username")
    .await?
    .type_str("rust_user")
    .await?;

// 选择下拉框选项
page.find_element("select#country")
    .await?
    .select_by_value("US")
    .await?;

4. 截图和PDF生成

// 截取整个页面
page.screenshot()
    .full_page(true)
    .save("screenshot.png")
    .await?;

// 生成PDF
page.pdf()
    .landscape(false)
    .scale(1.0)
    .save("output.pdf")
    .await?;

5. 网络请求拦截

use chromiumoxide::handler::network::RequestPattern;

// 设置请求拦截
let pattern = RequestPattern::builder()
    .url_str("*.png")
    .resource_type("Image")
    .build();
    
page.set_request_interception(&[pattern]).await?;

// 处理被拦截的请求
while let Some(req) = page.next_request().await {
    if req.url().ends_with(".png") {
        req.abort().await?;
    } else {
        req.continue_request().await?;
    }
}

高级用法

并行控制多个页面

let pages = browser.new_pages(3).await?;  // 创建3个新页面
for (i, page) in pages.into_iter().enumerate() {
    page.goto(&format!("https://example.com/page{}", i)).await?;
    // 其他操作...
}

执行复杂JavaScript

let result = page.evaluate(
    r#"
    (function() {
        const elements = document.querySelectorAll('.item');
        return Array.from(elements).map(el => el.textContent);
    })()
    "#
).await?;

println!("提取的内容: {:?}", result);

完整示例Demo

下面是一个完整的chromiumoxide使用示例,展示了从启动浏览器到抓取页面数据的完整流程:

use chromiumoxide::browser::{Browser, BrowserConfig};
use chromiumoxide::page::Page;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 启动浏览器实例(无头模式)
    let (browser, mut handler) = Browser::launch(
        BrowserConfig::builder()
            .with_head()
            .build()?
    ).await?;

    // 处理浏览器事件的任务
    let handle = tokio::task::spawn(async move {
        while let Some(h) = handler.next().await {
            if h.is_err() {
                break;
            }
        }
    });

    // 2. 创建新页面并导航
    let page = browser.new_page("https://www.rust-lang.org").await?;
    page.wait_for_navigation().await?;

    // 3. 获取页面信息
    let title = page.evaluate("document.title").await?;
    println!("页面标题: {:?}", title);

    // 4. 截图保存
    page.screenshot()
        .full_page(true)
        .save("rust_lang.png")
        .await?;

    // 5. 执行复杂JavaScript提取数据
    let items = page.evaluate(
        r#"
        (function() {
            const items = [];
            document.querySelectorAll('a').forEach(link => {
                items.push({
                    text: link.innerText,
                    href: link.href
                });
            });
            return items;
        })()
        "#
    ).await?;
    
    println!("提取到的链接: {:?}", items);

    // 6. 关闭浏览器
    browser.close().await?;
    handle.await?;
    
    Ok(())
}

注意事项

  1. 首次运行会自动下载Chromium浏览器,可能需要较长时间
  2. 无头模式适合生产环境,调试时可去掉with_head()配置
  3. 确保正确处理异步任务和错误
  4. 复杂的页面可能需要添加等待逻辑

chromiumoxide为Rust开发者提供了强大的浏览器自动化能力,特别适合需要高性能爬取或测试的场景。相比其他语言的类似工具,它能提供更好的内存安全性和并发性能。

回到顶部