use drission::prelude::*;
const PAGE: &str = r#"<!doctype html>
<html><head><meta charset="utf-8"><title>drission 练习页</title></head>
<body>
<h1 id="title">你好 drission</h1>
<ul id="list">
<li class="item">苹果</li>
<li class="item">香蕉</li>
<li class="item">橙子</li>
</ul>
<input id="kw" type="text" />
<a id="link" href="https://apizero.cn">官网</a>
</body></html>"#;
#[tokio::main]
async fn main() -> drission::Result<()> {
let headless = std::env::var("HL").map(|v| v != "0").unwrap_or(true);
println!("==== drission 教学示例开始(headless={headless})====\n");
let browser = ChromiumBrowser::launch(ChromiumOptions::new().headless(headless)).await?;
let tab = browser.new_tab(Some("about:blank")).await?;
tab.set_content(PAGE).await?;
let title = tab.title().await?;
println!("[②] 页面标题 = {title:?}");
let title_el = tab.ele("#title").await?;
println!("[③] #title 文本 = {:?}", title_el.text().await?);
println!("[③] #title 标签 = {:?}", title_el.tag().await?);
let title_el2 = title_el.clone();
println!(
"[③] 克隆的句柄仍指向同一元素,文本 = {:?}",
title_el2.text().await?
);
let items = tab.eles("css:.item").await?;
println!("[④] 找到 {} 个 .item", items.len());
for it in &items {
println!(" - {:?}", it.text().await?);
}
println!(
"[④] 遍历用的是 &items,所以这里还能再用 items.len() = {}",
items.len()
);
let link = tab.ele("#link").await?;
match link.attr("href").await? {
Some(href) => println!("[⑤] #link 的 href = {href}"),
None => println!("[⑤] #link 没有 href 属性"),
}
if let Some(t) = tab.ele_text("#not-exist").await? {
println!("[⑤] 不该出现:{t}");
} else {
println!("[⑤] #not-exist 不存在 → 得到 None(优雅,不 panic)");
}
let count = dump_list(&tab, "css:.item").await?;
println!("[⑥] dump_list 通过借用 &tab 读到了 {count} 个 item(tab 还在 main 手里)");
let tab_bg = tab.clone();
let handle = tokio::spawn(async move {
let title = tab_bg.title().await?;
drission::Result::Ok(title)
});
let bg_title = handle.await.expect("后台任务不该 panic")?;
println!("[⑦] 后台任务(move 进闭包的 tab 克隆)读到标题 = {bg_title:?}");
let sentence = "drission 很好用";
let w = first_word(sentence);
println!(
"[⑧] first_word({sentence:?}) = {w:?}(返回值借用了 sentence,所以 sentence 得比它活得久)"
);
for sel in ["#kw", "@id:kw", "登录", "xpath://a"] {
let q: Query = parse_locator(sel);
println!(" parse_locator({sel:?}) = {q:?}");
}
let doc = StaticElement::parse(PAGE)?; let li = doc.eles("css:.item")?; println!("[⑨] StaticElement 离线解析到 {} 个 .item:", li.len());
for e in &li {
println!(" - {}", e.text()?); }
browser.quit().await?;
println!("\n==== 全部 9 课完成,你已经把这个库跑通了一遍 ====");
Ok(())
}
async fn dump_list(tab: &ChromiumTab, selector: &str) -> drission::Result<usize> {
let eles = tab.eles(selector).await?;
for (i, e) in eles.iter().enumerate() {
println!(" [{i}] {:?}", e.text().await?);
}
Ok(eles.len())
}
fn first_word<'a>(s: &'a str) -> &'a str {
match s.trim_start().split_whitespace().next() {
Some(w) => w,
None => "",
}
}