问题描述
我开始使用 Druid crate 和 Crabler crate 编写一个程序,以制作我可以探索其数据的网络抓取应用程序。在我花了一段时间构建这个程序很久之后,我才意识到合并同步和异步编程是一个坏主意。我现在想要做的是在应用程序打开时(最好每小时运行一次)。
现在,直到应用程序关闭后,scraper 才会运行。我尝试使用 Tokio 的 spawn
来创建一个在应用程序打开之前启动的单独线程,但这不起作用,因为 Crabler 未来没有“发送”特征。
我尝试制作一个最小的功能程序,如下所示。 title_handler
未按预期运行,但在其他方面表明我遇到了问题。
是否可以允许 WebScraper 在应用程序打开时运行?如果是这样,如何?
编辑:我尝试使用 task::spawn_blocking()
运行应用程序,但它抛出了大量错误,包括德鲁伊没有实现 Send
特性。
use crabler::*;
use druid::widget::prelude::*;
use druid::widget::{Align,Flex,Label,TextBox};
use druid::{AppLauncher,Data,Lens,WindowDesc,WidgetExt};
const ENTRY_PREFIX: [&str; 1] = ["https://duckduckgo.com/?t=ffab&q=rust&ia=web"];
// Use WebScraper trait to get each item with the ".result__title" class
#[derive(WebScraper)]
#[on_response(response_handler)]
#[on_html(".result__title",title_handler)]
struct Scraper {}
impl Scraper {
// Print webpage status
async fn response_handler(&self,response: Response) -> Result<()> {
println!("Status {}",response.status);
Ok(())
}
async fn title_handler(&self,_: Response,el: Element) -> Result<()> {
// Get text of element
let title_data = el.children();
let title_text = title_data.first().unwrap().text().unwrap();
println!("Result is {}",title_text);
Ok(())
}
}
// Run scraper to get info from https://duckduckgo.com/?t=ffab&q=rust&ia=web
async fn one_scrape() -> Result<()> {
let scraper = Scraper {};
scraper.run(Opts::new().with_urls(ENTRY_PREFIX.to_vec()).with_threads(1)).await
}
#[derive(Clone,Lens)]
struct Init {
tag: String,}
fn build_ui() -> impl Widget<Init> {
// Search Box
let l_search = Label::new("Search: ");
let tb_search = TextBox::new()
.with_placeholder("Enter tag to search")
.lens(Init::tag);
let search = Flex::row()
.with_child(l_search)
.with_child(tb_search);
// Describe layout of UI
let layout = Flex::column()
.with_child(search);
Align::centered(layout)
}
#[async_std::main]
async fn main() -> Result<()> {
// Describe the main window
let main_window = WindowDesc::new(build_ui())
.title("Title Tracker")
.window_size((400.0,400.0));
// Create starting app state
let init_state = Init {
tag: String::from("#"),};
// Start application
AppLauncher::with_window(main_window)
.launch(init_state)
.expect("Failed to launch application");
one_scrape().await
}
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)