Rust中的异步编程:构建简单的网页爬虫
一、什么是Rust中的Futures和Async?
在Rust中,异步编程基于future(未来)的概念。一个future表示一个当前可能不可用,但将来某个时候可以获得的值。Rust中的Future特征定义了这一概念,任何实现了该特征的类型都表示一个future。
Rust中的异步编程关键元素包括:
-
async:async关键字标记函数或代码块,可以被中断并稍后恢复。当你标记一个函数为async时,它将返回一个Future,而不是直接返回结果。 -
await:await关键字用于在async函数中暂停函数的执行,直到待处理的future完成。
1.1.示例:并发地获取网页
让我们创建一个命令行程序,它并发地获取两个网页,提取它们的<title>元素,并打印第一个完成的网页的标题。我们将使用trpl crate,它提供了一个简化Rust异步编程的抽象,封装了像futures和tokio这样的常见异步库。
1.2.设置项目
首先,我们需要设置一个新的Rust项目,并将trpl crate作为依赖项。
$ cargo new hello-async
$ cd hello-async
$ cargo add trpl
1.3.第一步:定义page_title函数
为了从网页中获取<title>元素,我们定义一个异步函数page_title。该函数将使用trpl::get方法发送HTTP GET请求到指定的URL并获取网页内容。然后,我们通过CSS选择器提取<title>元素。
这是page_title函数的实现:
use trpl::Html;/// 异步函数,获取指定URL页面的<title>元素
async fn page_title(url: &str) -> Option<String> {// 使用trpl库的get方法获取网页内容,text()方法返回网页的文本内容let response_text = trpl::get(url).await.text().await;// 解析HTML并查找<title>标签,返回标题内容Html::parse(&response_text).select_first("title") // 使用CSS选择器查找第一个<title>元素.map(|title| title.inner_html()) // 如果找到了<title>,返回其内部HTML内容
}
1.3.1.解释:
- 我们将函数标记为
async,因为我们使用了异步操作,如获取URL (get(url)) 和读取响应体 (text()),这些都是异步操作。 get(url)和text()都是异步操作,所以我们使用await等待它们完成。- 获取到响应后,我们解析HTML并使用
select_first("title")方法查找第一个<title>元素。 - 最后,我们返回
<title>元素的内部HTML内容,即页面的标题,返回类型是Option<String>。
1.4.第二步:在main函数中调用page_title
接下来,我们需要在main函数中调用page_title函数。然而,Rust不允许将main函数标记为异步函数,因此我们必须使用一个运行时来执行异步代码。我们可以使用trpl::run函数,它初始化异步运行时并运行page_title函数返回的future。
这是更新后的main函数:
fn main() {// 从命令行参数中获取两个URLlet url1 = std::env::args().nth(1).expect("Please provide the first URL");let url2 = std::env::args().nth(2).expect("Please provide the second URL");// 使用trpl::run运行一个异步代码块trpl::run(async {// 创建两个异步任务,分别获取两个URL的<title>元素let title_fut_1 = page_title(&url1);let title_fut_2 = page_title(&url2);// 使用race函数并发地执行两个任务,返回第一个完成的结果let result = trpl::race(title_fut_1, title_fut_2).await;// 根据race函数的结果打印第一个完成的页面标题match result {trpl::Either::Left(Some(title)) => println!("The title for {} is: {}", url1, title),trpl::Either::Right(Some(title)) => println!("The title for {} is: {}", url2, title),_ => println!("Could not fetch title for one or both URLs."),}});
}
1.5.第三步:竞速两个URL
在这个示例中,我们从命令行传入两个URL,分别获取它们的标题,并返回第一个完成的网页。我们使用trpl::race函数,它返回一个值,指示哪个future先完成。
1.5.1解释:
- 我们并发地调用
page_title函数,分别创建两个future:title_fut_1和title_fut_2。 - 使用
trpl::race等待哪个future先完成。它返回一个值,表示哪个future完成得更早,我们可以根据这个结果处理。 - 使用
match语句打印第一个完成的页面的标题。如果某个页面没有<title>标签,我们也会处理这种情况。
1.6.运行程序
要运行该程序,您需要提供两个URL作为命令行参数。下面是运行爬虫的示例:
$ cargo run -- https://www.rust-lang.org https://www.example.com
输出将显示第一个完成加载的页面的标题:
The title for https://www.rust-lang.org is: Rust Programming Language
1.7.理解Rust中的Async和Futures
在这个示例中,async关键字将函数转换为返回Future的函数,Future代表一个将在未来某个时刻可用的值。这是Rust中异步编程的基本概念。
-
懒惰的Futures:在Rust中,futures是懒惰的,意味着它们不会在创建时立即执行,而是直到使用
await显式等待它们时才会执行。这使得Rust能够优化异步任务并避免不必要的计算。 -
状态机和执行器:每个
async函数都被Rust编译器转换为一个状态机。这些状态机允许程序在await点暂停执行,并在未来某个时刻恢复。异步任务的执行由执行器管理,例如trpl::run函数所提供的执行器。 -
并发性:通过让两个URL并发执行,我们利用了异步编程的优势,使程序比顺序执行更高效。
二、结论
我们成功地构建了一个简单的异步网页爬虫,能够并发地获取两个网页,并打印第一个完成的网页的标题。在这个过程中,我们学习了Rust中的异步编程的基本概念,包括futures、async/await和并发性。
通过使用trpl crate并理解Rust的异步系统工作原理,你现在可以创建更复杂的异步应用程序,充分利用Rust的并发模型。祝编程愉快!
相关文章:
Rust中的异步编程:构建简单的网页爬虫
一、什么是Rust中的Futures和Async? 在Rust中,异步编程基于future(未来)的概念。一个future表示一个当前可能不可用,但将来某个时候可以获得的值。Rust中的Future特征定义了这一概念,任何实现了该特征的类…...
springai系列(二)从0开始搭建和接入azure-openai实现智能问答
文章目录 前言1.从0开始搭建项目2.进入微软openai申请key3.配置application.yaml4.编写controller5.测试源码下载地址总结 前言 之前使用openai的官网的api需要科学上网,但是我们可以使用其他的代理间接实现使用chatgpt的相关模型,解决这个问题。比如:本…...
flutter 局部刷新控件Selector源码实现原理
Flutter 中的 Selector 组件是 provider 包提供的一个优化工具,用于在状态管理中仅选择所需数据片段,避免不必要的 Widget 重建。其实现原理基于以下几个关键点: 1. 核心设计目标 选择性重建:仅当特定数据变化时触发 Widget 重建&…...
Eclipse 编译项目指南
Eclipse 编译项目指南 引言 Eclipse 是一款功能强大的集成开发环境(IDE),广泛用于Java、C/C、Python等多种编程语言的开发。在Eclipse中编译项目是进行软件开发的基础步骤。本文将详细介绍如何在Eclipse中编译项目,包括项目设置…...
Go在1.22版本修复for循环陷阱
记录 前段时间升级Go版本碰到一个大坑,先记录。 先上代码案例: func main() {testClosure() }func testClosure() {for i : 0; i < 5; i {defer func() {fmt.Println(i)}()} }在1.22之下(不包括1.22)版本: 输出的…...
c++_sort函数
sort介绍 在C/C中,要想应用排序算法,可以使用c语言的qsort,也可以使用c的sort 。 1)qsort 是 C 标准库提供的一个通用排序函数,位于 stdlib.h 头文件中。 qsort 适用于 C 语言中的数组。 2)sort 是 C 中STL的泛型算法…...
【Stable Diffusion】AnimatedDiff--AI动画 插件使用技巧分享;文生视频、图生视频、AI生成视频工具;
本专栏主要记录人工智能的应用方面的内容,包括chatGPT、DeepSeek、AI绘画等等; 在当今AI的热潮下,不学习AI,就要被AI淘汰;所以欢迎小伙伴加入本专栏和我一起探索AI的应用,通过AI来帮助自己提升生产力; 本文的目标就是让每一个读者,都能学会并掌握AnimateDiff的使用;成…...
可视化约瑟夫生死环小游戏
这是一个基于Tkinter的图形界面应用程序,用于模拟约瑟夫环问题。约瑟夫环问题是一个经典的数学问题,描述的是N个人围成一圈,从第一个人开始报数,每数到第M个人就将其淘汰,然后从下一个人继续报数,直到剩下最…...
【深入理解JWT】从认证授权到网关安全
最近的项目学习中,在进行登陆模块的用户信息验证这一部分又用到了JWT的一些概念和相关知识,特在此写了这篇文章、方便各位笔者理解JWT相关概念 目录 先来理解JWT是什么? 区分有状态认证和无状态认证 有状态认证 VS 无状态认证 JWT令牌的…...
学习路之PHP --TP6异步执行功能 (无需安装任何框架)
学习路之PHP --异步执行功能 (无需安装任何框架) 简介一、工具类二、调用三、异步任务的操作四、效果: 简介 执行异步任务是一种很常见的需求,如批量发邮箱,短信等等执行耗时任务时,需要程序异步执行&…...
DeepSeek-R1:GPU编程自动化加速的新纪元
摘要 DeepSeek-R1是由斯坦福大学和普林斯顿大学研究者共同开发的项目,其自研的CUDA核心在性能测试中取得了卓越成绩,超越了o1和Claude 3.5 Sonnet,位居榜首。尽管DeepSeek-R1目前仅在约20%的任务中实现了对PyTorch Eager模式的性能超越&#…...
CSS 对齐:深入理解与技巧实践
CSS 对齐:深入理解与技巧实践 引言 在网页设计中,元素的对齐是至关重要的。一个页面中元素的对齐方式直接影响到页面的美观度和用户体验。CSS 提供了丰富的对齐属性,使得开发者可以轻松实现各种对齐效果。本文将深入探讨 CSS 对齐的原理、方法和技巧,帮助开发者更好地掌握…...
vue深拷贝:1、使用JSON.parse()和JSON.stringify();2、使用Lodash库;3、使用深拷贝函数(采用递归的方式)
文章目录 引言三种方法的优缺点在Vue中,实现数组的深拷贝I JSON.stringify和 JSON.parse的小技巧深拷贝步骤缺点:案例1:向后端请求路由数据案例2: 表单数据处理时复制用户输入的数据II 使用Lodash库步骤适用于复杂数据结构和需要处理循环引用的场景III 自定义的深拷贝函数(…...
九、数据治理架构流程
一、总体结构 《数据治理架构流程图》(Data Governance Architecture Flowchart) 水平结构:流程图采用水平组织,显示从数据源到数据应用的进程。 垂直结构:每个水平部分进一步划分为垂直列,代表数据治理的…...
【数据结构】 最大最小堆实现优先队列 python
堆的定义 堆(Heap)是一种特殊的完全二叉树结构,通常分为最大堆和最小堆两种类型。 在最大堆中,父节点的值总是大于或等于其子节点的值; 而在最小堆中,父节点的值总是小于或等于其子节点的值。 堆常用于实…...
51c自动驾驶~合集52
我自己的原文哦~ https://blog.51cto.com/whaosoft/13383340 #世界模型如何推演未来的千万种可能 驾驶世界模型(DWM),专注于预测驾驶过程中的场景演变,已经成为追求自动驾驶的一种有前景的范式。这些方法使自动驾驶系统能够更…...
服务 ‘Sql Server VSS writer‘ (SQLWriter) 在安装 LocalDB 时无法启动
安装Microsoft Visual C 2015-2019 Redistributable (x64)...
【我的 PWN 学习手札】House of Husk
House of Husk House of Husk是利用格式化输出函数如printf、vprintf在打印输出时,会解析格式化字符如%x、%lld从而调用不同的格式化打印方法(函数)。同时C语言还提供了注册自定义格式化字符的方法。注册自定义格式化字符串输出方法…...
Nmap使用指南
Nmap使用指南 Nmap (网络映射器) 是一款强大的应用网络扫描和安全核查工具,适合于网络管理和安全专家。本文将介绍Nmap的基本使用方法,包括基本命令和常用功能。 1. 基本使用方式 Nmap的基本命令格式如下: nmap [选项] 目标地址目标地址 可…...
傅里叶分析
傅里叶分析之掐死教程(完整版)更新于2014.06.06 要让读者在不看任何数学公式的情况下理解傅里叶分析。 傅里叶分析不仅仅是一个数学工具,更是一种可以彻底颠覆一个人以前世界观的思维模式。但不幸的是,傅里叶分析的公式看起来太复…...
从零开始用react + tailwindcss + express + mongodb实现一个聊天程序(五) 实现登录功能
1.登录页面 完善登录页面 和注册差不多 直接copy signUpPage 内容 再稍微修改下 import { useState } from "react"; import { useAuthStore } from "../store/useAuthStore"; import { MessageSquare,Mail,Lock,Eye, EyeOff,Loader2} from "lucide…...
基于多层感知机(MLP)实现MNIST手写体识别
实现步骤 下载数据集处理好数据集确定好模型(初始化模型参数等等)确定优化函数(损失函数也称为目标函数)和优化方法(一般选用随机梯度下降 SDG )进行模型的训练进行模型的评估 import torch import torch…...
如何使用useContext进行全局状态管理?
在 React 中,使用 useContext 进行全局状态管理是一种有效的方法,尤其在需要在多个组件之间共享状态时。useContext 允许你在组件树中传递数据,而无需通过每个组件的 props 逐层传递。以下是关于如何使用 useContext 进行全局状态管理的详细指…...
【机器学习】Logistic回归#1基于Scikit-Learn的简单Logistic回归
主要参考学习资料: 《机器学习算法的数学解析与Python实现》莫凡 著 前置知识:线性代数-Python 目录 问题背景数学模型类别表示Logistic函数假设函数损失函数训练步骤 代码实现特点 问题背景 分类问题是一类预测非连续(离散)值的…...
8.Dashboard的导入导出
分享自己的Dashboard 1. 在Dashboard settings中选择 JSON Model 2. 导入 后续请参考第三篇导入光放Dashboard,相近...
next.js-学习2
next.js-学习2 1. https://nextjs.org/learn/dashboard-app/getting-started2. 模拟的数据3. 添加样式4. 字体,图片5. 创建布局和页面页面导航 1. https://nextjs.org/learn/dashboard-app/getting-started /app: Contains all the routes, components, and logic …...
视频推拉流EasyDSS直播点播平台授权激活码无效,报错400的原因是什么?
在当今数字化浪潮中,视频推拉流 EasyDSS 视频直播点播平台宛如一颗璀璨的明珠,汇聚了视频直播、点播、转码、精细管理、录像、高效检索以及时移回看等一系列强大功能于一身,全方位构建起音视频服务生态。它既能助力音视频采集,精准…...
【论文详解】Transformer 论文《Attention Is All You Need》能够并行计算的原因
文章目录 前言一、传统 RNN/CNN 存在的串行计算问题二、Transformer 如何实现并行计算?三、Transformer 的 Encoder 和 Decoder 如何并行四、结论 前言 亲爱的家人们,创作很不容易,若对您有帮助的话,请点赞收藏加关注哦ÿ…...
Fisher信息矩阵(Fisher Information Matrix,简称FIM)
Fisher信息矩阵简介 Fisher信息矩阵(Fisher Information Matrix,简称FIM)是统计学和信息理论中的一个重要概念,广泛应用于参数估计、统计推断和机器学习领域。它以统计学家罗纳德费希尔(Ronald Fisher)的名…...
基础设施安全(Infrastructure Security)是什么?
基础设施安全(Infrastructure Security)指的是保护IT基础设施(包括物理和云端的服务器、网络设备、存储、数据库等)免受网络攻击、数据泄露、未授权访问、系统故障等威胁的各种安全措施和技术。 1. 基础设施安全的主要组成部分 &…...
