14个版本
0.5.7 | 2023年7月26日 |
---|---|
0.5.3 | 2023年6月10日 |
0.5.2 | 2022年6月20日 |
0.4.0 | 2022年1月29日 |
0.2.1 | 2021年11月27日 |
#101 在 解析器实现 中
7,613 每月下载量
在 5 个 软件包中(直接使用4个)
280KB
6.5K SLoC
html5gum
html5gum
是一个符合WHATWG规范的HTML标记解析器。
use std::fmt::Write;
use html5gum::{Tokenizer, Token};
let html = "<title >hello world</title>";
let mut new_html = String::new();
for token in Tokenizer::new(html).infallible() {
match token {
Token::StartTag(tag) => {
write!(new_html, "<{}>", String::from_utf8_lossy(&tag.name)).unwrap();
}
Token::String(hello_world) => {
write!(new_html, "{}", String::from_utf8_lossy(&hello_world)).unwrap();
}
Token::EndTag(tag) => {
write!(new_html, "</{}>", String::from_utf8_lossy(&tag.name)).unwrap();
}
_ => panic!("unexpected input"),
}
}
assert_eq!(new_html, "<title>hello world</title>");
标记解析器做什么和不做什么
html5gum
完全实现了 WHATWG HTML规范中的13.2.5,即能够对HTML文档进行标记化并通过 html5lib的标记解析器测试套件。由于它只是一个标记解析器,这意味着
html5gum
不 实现字符集检测。 此实现接受和返回字节,但假定UTF-8。它可以优雅地处理无效的UTF-8。html5gum
不 纠正错误嵌套的标签。html5gum
不 识别隐式自闭合元素,如<img>
,作为标记解析器,它将简单地发出一个开始标记。然而,它确实会发出一个自闭合标签<img .. />
。html5gum
不实现DOM,遗憾的是,在HTML规范中,构建DOM(“树构建”)会影响标记化操作。例如,请参阅 此示例代码 以了解这会导致哪些问题。html5gum
通常不 符合WHATWG规范中的浏览器级HTML 解析器。这在未来可能会改变,请参阅 问题21。
考虑到这些注意事项,html5gum
几乎可以解析标记浏览器能够解析的任何内容。
Emitter
特性
html5gum
的一个显著特点是,您可以提供自己的标记数据结构,并通过实现Emitter
特性来挂钩标记创建。这允许您
-
将所有针对HTML标签的分配重写为使用自定义分配器或数据结构。
-
有效地过滤掉不感兴趣的数据类别,而无需为其分配内存。例如,如果标记之间的任何纯文本对您来说都不感兴趣,您可以实现相应的特质方法作为空操作,从而避免创建纯文本标记的任何开销。
请参阅custom_emitter
示例,了解实际效果。
其他特性
- 无不安全Rust
- 唯一的依赖项是
jetscii
,可以通过crate特性禁用(见Cargo.toml
)
其他HTML解析器
html5gum
的创建是为了高效地解析HTML标签杂烩。之前的选项是
-
使用quick-xml或xmlparser,并进行一些修改,以使任何一个都能处理坏HTML。对于某些(相当大)的HTML输入,这效果很好(尤其是
quick-xml
可以配置为对解析错误非常宽容)且解析速度极快。但它们都不能解析所有的HTML。对于我的用例,
html5gum
比quick-xml
慢约2倍。 -
使用html5ever自己的标记器,以尽可能减少树构建的开销。这虽然可行,但在我自己的用例中性能较差(比
quick-xml
慢10-15倍)。 -
使用lol-html,其性能可能至少与
html5gum
一样好,但它提供了一个基于闭包的API,我没有成功地在我的用例中使其工作。
词源
为什么这个库叫html5gum
?
-
G.U.M: Giant Unreadable Match-statement
-
<在此处插入“像吃5 gum一样解析HTML”的meme图片>
许可证
在MIT许可证下发布,请参阅./LICENSE
。