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