我如何避免在此代码中使用全局可变变量?
How might I avoid a global mutable variable in this code?
如果在 this website 上找到某个 div
,以下代码将打印 There is page two.
:
use reqwest;
use select::document::Document;
use select::predicate::Name;
use std::io;
static mut DECIDE: bool = false;
fn page_two_filter(x: &str, url: &str) {
if x == "pSiguiente('?pagina=2')" {
unsafe {
DECIDE = true;
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.for_each(|x| page_two_filter(x, url));
unsafe {
if DECIDE == true {
println!("There is page two.")
}
}
Ok(())
}
来自 Cargo.toml
的依赖项
[dependencies]
futures = "0.3.15"
reqwest = "0.11.9"
scraper = "0.12.0"
select = "0.5.0"
tokio = { version = "1", features = ["full"] }
是否有更安全的方法,即没有 unsafe
代码块来执行该代码的操作?
为了避免全局可变变量,我尝试重新定义 page_two_filter
和一个带有调用 page_two_filter
结果的 if 语句,如下所示:
fn page_two_filter(x: &str, url: &str) -> bool {
if x == "pSiguiente('?pagina=2')" {
return true;
}
false
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
if Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.for_each(|x| page_two_filter(x, url))
{
println!("There is page two.")
}
Ok(())
}
但是编译器不允许我这样做说:
mismatched types expected `()`, found `bool`
而不是 for_each()
,我猜你需要 find()
。
这个 returns Some( found_element )
如果找到或 None
如果没有找到。
然后您可以将 find()
返回的 Option
与 if let
、match
、is_some()
...
一起使用
if let Some(_) = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.find(|x| page_two_filter(x, url))
{
println!("There is page two.")
}
首先,
mismatched types expected ()
, found bool
错误是因为for_each闭包中println语句后没有分号
其次,过滤器实际上是一个 one-liner,它可以集成在那个闭包中
fn page_two_filter(x: &str, url: &str) -> bool {
x == "pSiguiente('?pagina=2')"
}
最后,您已经使用了各种迭代器方法,为什么不继续呢?
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin().read_line(&mut url).expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
if let Some(_) = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.find_map(|attr| if attr == "pSiguiente('?pagina=2')" {
Some(true)
} else {
None
}) {
println!("There is page two.");
}
Ok(())
}
您可以在第一次找到条件时使用 Iterator::any
which returns true,否则 false:
fn page_two_filter(x: &str, url: &str) -> bool {
x == "pSiguiente('?pagina=2')"
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
let found = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.any(|x| page_two_filter(x, url));
if found {
println!("There is page two.");
}
}
如果在 this website 上找到某个 div
,以下代码将打印 There is page two.
:
use reqwest;
use select::document::Document;
use select::predicate::Name;
use std::io;
static mut DECIDE: bool = false;
fn page_two_filter(x: &str, url: &str) {
if x == "pSiguiente('?pagina=2')" {
unsafe {
DECIDE = true;
}
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.for_each(|x| page_two_filter(x, url));
unsafe {
if DECIDE == true {
println!("There is page two.")
}
}
Ok(())
}
来自 Cargo.toml
的依赖项[dependencies]
futures = "0.3.15"
reqwest = "0.11.9"
scraper = "0.12.0"
select = "0.5.0"
tokio = { version = "1", features = ["full"] }
是否有更安全的方法,即没有 unsafe
代码块来执行该代码的操作?
为了避免全局可变变量,我尝试重新定义 page_two_filter
和一个带有调用 page_two_filter
结果的 if 语句,如下所示:
fn page_two_filter(x: &str, url: &str) -> bool {
if x == "pSiguiente('?pagina=2')" {
return true;
}
false
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
if Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.for_each(|x| page_two_filter(x, url))
{
println!("There is page two.")
}
Ok(())
}
但是编译器不允许我这样做说:
mismatched types expected `()`, found `bool`
而不是 for_each()
,我猜你需要 find()
。
这个 returns Some( found_element )
如果找到或 None
如果没有找到。
然后您可以将 find()
返回的 Option
与 if let
、match
、is_some()
...
if let Some(_) = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.find(|x| page_two_filter(x, url))
{
println!("There is page two.")
}
首先,
mismatched types expected
()
, foundbool
错误是因为for_each闭包中println语句后没有分号
其次,过滤器实际上是一个 one-liner,它可以集成在那个闭包中
fn page_two_filter(x: &str, url: &str) -> bool {
x == "pSiguiente('?pagina=2')"
}
最后,您已经使用了各种迭代器方法,为什么不继续呢?
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin().read_line(&mut url).expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
if let Some(_) = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.find_map(|attr| if attr == "pSiguiente('?pagina=2')" {
Some(true)
} else {
None
}) {
println!("There is page two.");
}
Ok(())
}
您可以在第一次找到条件时使用 Iterator::any
which returns true,否则 false:
fn page_two_filter(x: &str, url: &str) -> bool {
x == "pSiguiente('?pagina=2')"
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Give me the URL with the search results?");
let mut url = String::new();
io::stdin()
.read_line(&mut url)
.expect("Failed to read line");
let url = url.trim();
let html = reqwest::get(url).await?.text().await?;
let found = Document::from(html.as_str())
.find(Name("div"))
.filter_map(|n| n.attr("onclick"))
.any(|x| page_two_filter(x, url));
if found {
println!("There is page two.");
}
}