Rust浏览器自动化库chromiumoxide_cdp的使用:通过Chrome DevTools协议实现高效网页操控与数据抓取
Rust浏览器自动化库chromiumoxide_cdp的使用:通过Chrome DevTools协议实现高效网页操控与数据抓取
chromiumoxide 提供了一个高级异步 API 来控制 Chrome 或 Chromium 通过 DevTools 协议。它支持所有类型的 Chrome DevTools 协议,并且可以启动一个 headless 或无头 Chrome/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?;
// 查找搜索框,输入搜索内容并回车
page.find_element("input#searchInput")
.await?
.click()
.await?
.type_str("Rust programming language")
.await?
.press_key("Enter")
.await?;
// 等待导航完成并获取页面HTML内容
let html = page.wait_for_navigation().await?.content().await?;
browser.close().await?;
handle.await;
Ok(())
}
当前API还缺少一些功能,但Page::execute
函数允许发送所有chromiumoxide_types::Command
类型。大多数Element
和Page
函数基本上只是简化的命令构造和组合,比如Page::pdf
:
pub async fn pdf(&self, params: PrintToPdfParams) -> Result<Vec<u8>> {
let res = self.execute(params).await?;
Ok(base64::decode(&res.data)?)
}
如果你需要其他功能,Page::execute
函数允许你编写自己的命令包装器。
添加到项目
chromiumoxide
支持async-std
和tokio
运行时。
默认使用async-std
运行时:
chromiumoxide = { git = "https://github.com/mattsse/chromiumoxide", branch = "main"}
要使用tokio
运行时,添加features = ["tokio-runtime"]
并设置default-features = false
:
chromiumoxide = { git = "https://github.com/mattsse/chromiumoxide", features = ["tokio-runtime"], default-features = false, branch = "main"}
自动下载Chromium
chromiumoxide
默认会尝试在运行的计算机上查找已安装的Chromium版本。也可以使用fetcher
自动下载和安装:
use std::path::Path;
use futures::StreamExt;
use chromiumoxide::browser::{BrowserConfig};
use chromiumoxide::fetcher::{BrowserFetcher, BrowserFetcherOptions};
#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let download_path = Path::new("./download");
async_std::fs::create_dir_all(&download_path).await?;
let fetcher = BrowserFetcher::new(
BrowserFetcherOptions::builder()
.with_path(&download_path)
.build()?,
);
let info = fetcher.fetch().await?;
let config = BrowserConfig::builder()
.chrome_executable(info.executable_path)
.build()?,
Ok(())
}
已知问题
- 当手动关闭对实验性类型的支持时(
export CDP_NO_EXPERIMENTAL=true
),为PDL文件生成的rust文件无法编译。
故障排除
问题: 一个新的chromium实例被启动但随后超时。
解决方案: 检查你的chromium语言设置是否为英语。chromiumoxide
尝试从chromium进程输出中解析调试端口,这仅限于英语。
许可证
MIT或Apache-2.0许可。
完整示例
这里是一个完整的网页抓取示例,展示了如何使用chromiumoxide抓取页面内容:
use futures::StreamExt;
use chromiumoxide::browser::{Browser, BrowserConfig};
use chromiumoxide::page::Page;
#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 配置浏览器并启动
let (browser, mut handler) = Browser::launch(
BrowserConfig::builder()
.with_head() // 使用UI界面
.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://example.com").await?;
// 等待页面加载完成
page.wait_for_navigation().await?;
// 获取页面标题
let title = page.title().await?;
println!("页面标题: {}", title);
// 获取页面HTML内容
let content = page.content().await?;
println!("页面内容长度: {} bytes", content.len());
// 截图
let screenshot = page.screenshot(None).await?;
std::fs::write("screenshot.png", screenshot)?;
// 关闭浏览器
browser.close().await?;
handle.await;
Ok(())
}
这个示例展示了chromiumoxide的基本功能,包括:
- 启动浏览器
- 创建新页面
- 导航到URL
- 获取页面信息
- 截图
- 关闭浏览器
你可以根据需要扩展这个示例,添加更多的自动化操作,如填写表单、点击元素、处理JavaScript等。
Rust浏览器自动化库chromiumoxide_cdp的使用指南
概述
chromiumoxide_cdp 是一个基于 Rust 的库,它通过 Chrome DevTools 协议 (CDP) 提供浏览器自动化功能。这个库允许开发者以编程方式控制 Chrome 或 Chromium 浏览器,实现网页操控、数据抓取等自动化任务。
主要特性
- 完整的 Chrome DevTools 协议支持
- 异步/等待友好的 API 设计
- 支持无头(Headless)和有头模式
- 网页导航、表单填写、点击等交互操作
- JavaScript 执行与结果获取
- 网络请求拦截与修改
- 页面截图和 PDF 生成
安装
在 Cargo.toml 中添加依赖:
[dependencies]
chromiumoxide = "0.7"
tokio = { version = "1.0", features = ["full"] }
完整示例代码
下面是一个结合多个功能的完整示例,展示如何使用chromiumoxide_cdp进行网页自动化操作:
use chromiumoxide::browser::{Browser, BrowserConfig};
use chromiumoxide::cdp::browser_protocol::network::events::RequestWillBeSent;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 1. 配置并启动浏览器
let config = BrowserConfig::builder()
.with_headless() // 无头模式
.build()?;
let (browser, mut handler) = Browser::launch(config).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("about:blank").await?;
page.goto("https://www.example.com").await?;
page.wait_for_navigation().await?;
// 3. 获取页面信息
let title = page.evaluate("document.title").await?;
println!("页面标题: {:?}", title);
// 4. 网络请求拦截示例
page.enable_network().await?;
let mut events = page.event_listener::<RequestWillBeSent>().await?;
tokio::task::spawn(async move {
while let Some(event) = events.next().await {
println!("拦截到请求: {}", event.request.url);
}
});
// 5. 执行复杂JavaScript
let result = page
.evaluate_with_args(
"({a, b}) => { return a * b; }",
json!({ "a": 6, "b": 7 })
)
.await?;
println!("计算结果: {}", result.value::<i32>()?);
// 6. 截图功能
page.screenshot()
.full_page(true)
.await?
.save("example_screenshot.png")
.await?;
// 7. 处理iframe示例(如果页面中有iframe)
if let Ok(iframes) = page.get_iframes().await {
if !iframes.is_empty() {
println!("发现 {} 个iframe", iframes.len());
}
}
// 关闭浏览器
browser.close().await?;
handle.await?;
Ok(())
}
代码说明
- 首先配置并启动浏览器实例,使用无头模式
- 创建新页面并导航到示例网站
- 获取并打印页面标题
- 设置网络请求拦截,打印所有请求URL
- 执行带有参数的JavaScript并获取结果
- 截取整个页面并保存为PNG文件
- 检查页面中的iframe并打印数量
注意事项
- 运行此代码前请确保已安装Chrome或Chromium浏览器
- 网络请求拦截功能会捕获所有请求,可能会影响性能
- 截图功能需要页面完全加载后才能获得完整效果
- 实际使用时请添加适当的错误处理逻辑