42 个版本
| 0.10.0-rc.2 | 2024 年 6 月 13 日 |
|---|---|
| 0.9.1 | 2024 年 1 月 23 日 |
| 0.9.0 | 2023 年 12 月 15 日 |
| 0.9.0-rc.1 | 2023 年 11 月 2 日 |
| 0.3.0-alpha.3 | 2020 年 11 月 12 日 |
#97 in 网络编程
每月 350 次下载
用于 2 crates
180KB
3.5K SLoC
parsoid
parsoid crate 是围绕 Parsoid HTML 的包装器,提供方便的访问器以进行处理和提取。
受 mwparserfromhell,parsoid-jsapi 启发,并在 Kuchiki (朽木) 的基础上构建。
快速入门
获取 HTML 并提取模板参数的值
use parsoid::prelude::*;
let client = ParsoidClient::new("https://en.wikipedia.org/w/rest.php", "parsoid-rs demo")?;
let code = client.get("Taylor_Swift").await?.into_mutable();
for template in code.filter_templates()? {
if template.name() == "Template:Infobox person" {
let birth_name = template.param("birth_name").unwrap();
assert_eq!(birth_name, "Taylor Alison Swift");
}
}
添加页面链接并将其转换为维基文本
use parsoid::prelude::*;
let client = ParsoidClient::new("https://en.wikipedia.org/w/rest.php", "parsoid-rs demo")?;
let code = client.get("Wikipedia:Sandbox").await?.into_mutable();
let link = WikiLink::new(
"./Special:Random",
&Wikicode::new_text("Visit a random page")
);
code.append(&link);
let wikitext = client.transform_to_wikitext(&code).await?;
assert!(wikitext.ends_with("[[Special:Random|Visit a random page]]"));
此 crate 不提供保存页面的功能,您需要使用类似 mwbot 的工具。
架构
从概念上讲,此 crate 在 HTML 处理库之上提供与维基相关的类型。有三个主要结构需要了解:Wikicode,Wikinode 和 Template。
Wikicode 表示整个维基页面的容器,相当于一个 <html> 或 <body> 节点。它提供了一些便利函数,如 filter_links(),以便轻松操作和修改特定的 Wikinode。(为了方便,Wikicode 也是一个 Wikinode。)
use parsoid::prelude::*;
let client = ParsoidClient::new("https://en.wikipedia.org/w/rest.php", "parsoid-rs demo")?;
let code = client.get("Taylor Swift").await?.into_mutable();
for link in code.filter_links() {
if link.target() == "You Belong with Me" {
// ...do something
}
}
仅针对常见类型提供筛选函数作为优化,但对于其他类型实现起来也很简单
use parsoid::prelude::*;
let client = ParsoidClient::new("https://en.wikipedia.org/w/rest.php", "parsoid-rs demo")?;
let code = client.get("Taylor Swift").await?.into_mutable();
let entities: Vec<HtmlEntity> = code
.descendants()
.filter_map(|node| node.as_html_entity())
.collect();
Wikinode 是一个枚举,表示所有类型的 Wikinode,主要是为了使函数能够接受/返回各种类型的节点。
Wikinode为处理特定类型的MediaWiki结构提供了便捷函数。例如,WikiLink类型包装了一个节点,例如:<a rel="mw:WikiLink" href="...">...</a>。它提供了访问或修改href属性的功能。要访问链接文本,需要使用.children()并修改或追加这些节点。标准修改器,如.append()和.insert_after()是WikinodeIterator特质的组成部分,该特质在预览中自动导入。
以下节点已经实现:
BehaviorSwitch:__TOC__Category:[[Category:Foo]]Comment:<!-- ... -->ExtLink:[https://example.org Text]Heading:== Some text ==HtmlEntity: IncludeOnly:<includeonly>foo</includeonly>InterwikiLink:[[:en:Foo]]LanguageLink:[[en:Foo]]Nowiki:<nowiki>[[foo]]</nowiki>Redirect:#REDIRECT [[Foo]]Section:包含一个Heading及其内容WikiLink:[[Foo|bar]]Generic- 对于我们没有更具体类型的任何节点。
每个Wikinode实际上都是围绕Rc<Node>的一个包装,使其克隆变得便宜。
模板
与 Wikinodes 不同,模板与 HTML 节点之间没有 1:1 的映射,一个节点中可能包含多个模板。获取 Template 实例的主要方法是调用 Wikicode::filter_templates()。
有关更多详情和示例,请参阅 Template 文档。
noinclude 和 onlyinclude
与模板类似,<noinclude> 和 <onlyinclude> 也没有与单个 HTML 节点进行 1:1 映射,因为它们可能跨越多个节点。获取 NoInclude 或 OnlyInclude 实例的主要方法是分别调用 filter_noinclude() 和 filter_onlyinclude()。
有关更多详情和示例,请参阅 模块级别 文档。
安全性
此库仅使用安全 Rust 实现,不应崩溃。然而,预期 HTML 达到一定程度的良好格式。例如,如果节点具有 rel="mw:WikiLink",则假定它是一个 <a> 元素。这不是为了完全防御任意 HTML,而应仅与来自 Parsoid 本身或通过此库或其他类似库变异的 HTML 一起使用(我们欢迎对此进行改进的贡献!)
此外,Wikicode 没有实现 Send,这意味着它不能在线程之间安全地共享。这是使用的基础 kuchikiki 库的限制。
提供 ImmutableWikicode 作为解决方案 - 它是 Send 且包含与 Wikicode 相同的所有信息,但它是不可变的。通过使用 into_immutable() 和 into_mutable() 或使用标准 From 和 Into 特性来在两者之间切换非常简单。
测试
使用 build_corpus 示例下载英语维基百科的前 500 篇特色文章以创建测试语料库。
featured_articles 示例将遍历这些下载的示例以测试解析代码、清理往返等。
贡献
parsoid 是 mwbot-rs 项目 的一部分。我们一直在寻找新的贡献者,如果您感兴趣,请 联系我们!
许可证
此软件包在 GPL-3.0-or-later 许可证下发布。有关详情,请参阅 COPYING。
依赖项
~5–18MB
~260K SLoC