我正在尝试按照此处的示例进行操作: https://rust-lang-nursery.github.io/rust-cookbook/web/scraping.html ,它利用 Reqwest 和 Select 来获取 html 响应,然后解析数据。
我使用的是 Reqwest 版本 0.10.4 和选择版本 0.4.3,这是它在示例中显示的版本。但是,我收到一个错误:
error[E0277]: the trait bound `reqwest::Response: std::io::Read` is not satisfied
--> src/main.rs:19:25
|
19 | Document::from_read(res)?
| ^^^ the trait `std::io::Read` is not implemented for `reqwest::Response`
|
::: /root/.cargo/registry/src/github.com-1ecc6299db9ec823/select-0.4.3/src/document.rs:31:25
|
31 | pub fn from_read<R: io::Read>(mut readable: R) -> io::Result<Document> {
| -------- required by this bound in `select::document::Document::from_read`
似乎 from_read 方法采用 Read 类型,但 reqwest::get 方法返回不同的类型。在将响应传递给 from_read 方法之前,是否必须首先完成某种类型的转换?
这是例子:
#[macro_use]
extern crate error_chain;
extern crate reqwest;
extern crate select;
use select::document::Document;
use select::predicate::Name;
error_chain! {
foreign_links {
ReqError(reqwest::Error);
IoError(std::io::Error);
}
}
fn main() -> Result<()> {
let res = reqwest::get("https://www.rust-lang.org/en-US/").await?;
Document::from_read(res)?
.find(Name("a"))
.filter_map(|n| n.attr("href"))
.for_each(|x| println!("{}", x));
Ok(())
}
最佳答案
reqwest::get
返回 Result<Response>
, 然后用 ?
你正在打开 Result
,意味着你现在有一个 Response
记录的对象 here .由于 Web 调用可以成功发生但仍然失败(请参阅 HTTP 非 200 代码),您应该检查响应代码,但由于这是为了学习,我们将忽略它。你想要的是一个实现 std::io::Read
的结构特质,阅读它表明 String
实现该特征。回到reqwest::Response
显示我们可以使用方法 text()
获取返回的字符串.所以你的代码现在变成了
let res = reqwest::get("https://www.rust-lang.org/en-US/")
.await?
.text()
.await?;
评论更新:现在的问题是Document::from_read
只接受 std::io::Read
作为参数,std::string::String
没有实现那个特性,而不是使用像 stringreader
这样的 crate 我们可以简单地使用 Document::from
作为文档实现 From<&'a str>
特质。
而且,与几乎所有事情一样,有多种方法可以解决这个问题。你也可以
直接使用
Document::from(res)
从字符串创建文档,或者将字符串转换为字节切片,实现读取,并使用
Document::from_read(res.as_bytes())
从中创建文档
关于select - 结合使用 Rust 库 reqwest 和 select,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61996298/