24次发布
0.7.8 | 2024年1月29日 |
---|---|
0.7.7 | 2022年8月25日 |
0.7.5 | 2022年4月18日 |
0.7.4 | 2022年3月20日 |
0.2.0 | 2021年3月27日 |
#57 in 解析器实现
19,739每月下载量
用于 43 个crate(34个直接使用)
145KB
3.5K SLoC
tl
tl是一个纯Rust编写的快速HTML解析器。
这个crate(目前)并不严格遵循HTML标准的完整规范,然而这通常对大多数用例来说不是问题。这个crate通常尝试支持大多数“合理”的HTML。不受规范的限制提供了更多的优化机会。如果您需要一个可以(非常快速)解析典型HTML文档且需要一个简单的API来操作DOM的解析器,请尝试这个crate。
如果您需要一个严格遵循标准的解析器,请考虑使用 html5ever、lol-html 或 html5gum。
使用方法
将 tl
添加到依赖中。
[dependencies]
tl = "0.7.8"
# or, with explicit SIMD support
# (requires a nightly compiler!)
tl = { version = "0.7.8", features = ["simd"] }
主函数是 tl::parse()
。它接受一个HTML源代码字符串并将其解析。需要注意的是,tl目前会静默忽略无效的标签,就像浏览器一样。有时,这意味着HTML文档的大块内容不会出现在结果树中。
let dom = tl::parse(r#"<p id="text">Hello</p>"#, tl::ParserOptions::default()).unwrap();
let parser = dom.parser();
let element = dom.get_element_by_id("text")
.expect("Failed to find element")
.get(parser)
.unwrap();
assert_eq!(element.inner_text(parser), "Hello");
示例
使用查询选择器API查找标签
let dom = tl::parse(r#"<div><img src="cool-image.png" /></div>"#, tl::ParserOptions::default()).unwrap();
let img = dom.query_selector("img[src]").unwrap().next();
assert!(img.is_some());
遍历HTML文档的子节点
let dom = tl::parse(r#"<div><img src="cool-image.png" /></div>"#, tl::ParserOptions::default()).unwrap();
let img = dom.nodes()
.iter()
.find(|node| {
node.as_tag().map_or(false, |tag| tag.name() == "img")
});
assert!(img.is_some());
修改锚标签的`href`属性
在实际场景中,您应该正确处理错误,而不是简单地解包。
let input = r#"<div><a href="/about">About</a></div>"#;
let mut dom = tl::parse(input, tl::ParserOptions::default())
.expect("HTML string too long");
let anchor = dom.query_selector("a[href]")
.expect("Failed to parse query selector")
.next()
.expect("Failed to find anchor tag");
let parser_mut = dom.parser_mut();
let anchor = anchor.get_mut(parser_mut)
.expect("Failed to resolve node")
.as_tag_mut()
.expect("Failed to cast Node to HTMLTag");
let attributes = anchor.attributes_mut();
attributes.get_mut("href")
.flatten()
.expect("Attribute not found or malformed")
.set("https://127.0.0.1/about");
assert_eq!(attributes.get("href").flatten(), Some(&"https://127.0.0.1/about".into()));
SIMD加速解析
这个crate有由解析器使用的工具函数,它们利用SIMD(例如,通过一次查看下一个16个字节来查找特定的字节,而不是逐个遍历字符串)。这些函数默认是禁用的,并且必须通过传递simd
功能标志显式启用,因为portable_simd
功能不稳定。这需要**夜间**编译器!
如果未启用simd
功能,它将回退到稳定的替代方案,这些替代方案不明确使用SIMD内省,但仍然得到了很好的优化,使用诸如手动循环展开等技术来移除边界检查和其他分支,这也有助于LLVM进一步优化代码,并可能自行生成SIMD指令。