使用reqwest+select实现简单网页爬虫

这篇文章是一个简单的Rust爬虫示例,我将爬取该网站的图书信息,包括书名、价格和库存状态。使用reqwest库发送HTTP请求,select库解析HTML内容。代码结构清晰,包含错误处理和基本的数据提取逻辑。

适合Rust爬虫新手学习网络请求、HTML解析和数据提取的基本流程。通过这个示例,你可以了解如何构建一个完整的爬虫工作流。

下面是一个简单、技术成熟且易于理解的 Rust 爬虫教程。我们将创建一个爬取图书信息(标题、价格)的爬虫,目标网站是专为爬虫练习设计的 books.toscrape.com。

项目准备

1、创建新项目:

cargo new book_scraper

cdbook_scraper

2、添加依赖 (Cargo.toml):

[dependencies]

reqwest= { version ="0.11", features =["blocking"]}# 同步HTTP客户端

scraper="0.13"# HTML解析库

select="0.5"# CSS选择器库

anyhow="1.0"# 简化错误处理

完整代码 (src/main.rs)

useanyhow::{Context,Result};

useselect::document::Document;

useselect::predicate::{Class,Name};

fnmain()->Result<()>{

// 目标网站

leturl="http://books.toscrape.com/";


// 发送HTTP GET请求

letresponse=reqwest::blocking::get(url)

.with_context(||format!("Failed to fetch {}",url))?;


// 确保请求成功

if!response.status().is_success() {

anyhow::bail!("Request failed with status: {}",response.status());

   }


// 读取HTML内容

lethtml_content=response.text()

.with_context(||"Failed to read response body")?;


// 解析HTML文档

letdocument=Document::from(html_content.as_str());


println!("开始爬取: {}",url);

println!("{:-^50}","图书列表");


// 查找所有图书条目

forbookindocument.find(Class("product_pod")) {

// 提取标题

lettitle=book.find(Name("h3")).next()

.and_then(|h3|h3.find(Name("a")).next())

.map(|a|a.text())

.unwrap_or_else(||"未知标题".to_string());


// 提取价格

letprice=book.find(Class("price_color")).next()

.map(|p|p.text())

.unwrap_or_else(||"未知价格".to_string());


// 提取库存状态

letstock=book.find(Class("instock")).next()

.map(|s|s.text().trim().to_string())

.unwrap_or_else(||"未知库存".to_string());


println!("书名: {}",title);

println!("价格: {}",price);

println!("库存: {}",stock);

println!("{}","-".repeat(40));

   }


println!("爬取完成!共找到 {} 本书",document.find(Class("product_pod")).count());

Ok(())

}

代码解析

1、HTTP请求 (reqwest):

letresponse=reqwest::blocking::get(url)?;

使用同步方式获取网页内容,适合简单爬虫

2、错误处理 (anyhow):

.with_context(||"错误描述")?;

提供友好的错误信息,自动处理错误传播

3、HTML解析 (select):

letdocument=Document::from(html_content.as_str());

将HTML内容加载到可查询的文档结构中

4、元素查找:

document.find(Class("product_pod"))

使用CSS选择器查找图书容器

5、数据提取:

book.find(Name("h3")).next().map(|h3|h3.text())

链式调用安全提取元素文本内容

运行结果示例

开始爬取: http://books.toscrape.com/

------------------图书列表------------------

书名: A Light in the Attic

价格: £51.77

库存: In stock

----------------------------------------

书名: Tipping the Velvet

价格: £53.74

库存: In stock

----------------------------------------

... (其他图书) ...

书名: The Black Maria

价格: £22.60

库存: In stock

----------------------------------------

爬取完成!共找到 20 本书

进阶功能添加

1、保存到CSV文件

添加依赖:

csv = "1.1"

修改代码:

use csv::Writer;

// 在main函数开头添加:

let mut wtr = Writer::from_path("books.csv")?;

wtr.write_record(&["书名", "价格", "库存"])?;

// 在循环内替换打印语句为:

wtr.write_record(&[&title, &price, &stock])?;

// 在main函数结尾添加:

wtr.flush()?;

println!("数据已保存到 books.csv");

2、自动翻页

let mut page = 1;

let mut total_books = 0;

loop {

let url = format!("http://books.toscrape.com/catalogue/page-{}.html", page);

// ...爬取逻辑...

// 检查是否有下一页

if document.find(Class("next")).next().is_none() {

break;

}

page += 1;

// 添加延时防止请求过快

std::thread::sleep(std::time::Duration::from_secs(1));

}

注意事项

1、尊重网站规则:

添加请求延时(至少1秒)

检查robots.txt(本例中http://books.toscrape.com/robots.txt允许爬取)

std::thread::sleep(std::time::Duration::from_secs(1));

2、处理异常:

网络错误

HTML结构变化

.unwrap_or_else(|| "未知".to_string());

3、用户代理设置:

let client = reqwest::blocking::Client::builder()

.user_agent("Mozilla/5.0 (学习用爬虫)")

.build()?;

client.get(url).send()?;

这个爬虫包含了爬虫的核心流程:请求 → 解析 → 提取 → 存储,使用成熟稳定的库实现,适合 Rust 新手学习。可根据需求扩展多线程、代理支持等高级功能。

到此就爬取完成!程序统计了找到的图书数量并显示结果。实际应用中,你可以添加CSV保存功能将数据存储到文件,或实现自动翻页爬取全站内容。注意在实际使用时添加请求延时,遵守robots.txt规则,并完善错误处理机制。这个基础爬虫可以扩展为更复杂的项目,如添加代理支持、并发处理或用户登录功能。希望这个示例能帮助你入门Rust爬虫开发!

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容