17 个版本

使用 Rust 2015 版

0.8.1 2017 年 3 月 4 日
0.7.4 2016 年 10 月 25 日
0.7.1 2015 年 12 月 10 日
0.7.0 2015 年 11 月 12 日
0.6.2 2015 年 7 月 14 日

#1342 in 文本处理

Download history 47/week @ 2024-03-16 23/week @ 2024-03-23 44/week @ 2024-03-30 55/week @ 2024-04-06 38/week @ 2024-04-13 46/week @ 2024-04-20 71/week @ 2024-04-27 47/week @ 2024-05-04 69/week @ 2024-05-11 68/week @ 2024-05-18 21/week @ 2024-05-25 45/week @ 2024-06-01 37/week @ 2024-06-08 59/week @ 2024-06-15 49/week @ 2024-06-22 13/week @ 2024-06-29

162 每月下载量
用于 crowbook

LGPL-2.1+

84KB
1.5K SLoC

Caribon

用 Rust 编写的重复检测器。

Build Status

演示服务器

如果您想了解 Caribon 的功能而不需要下载任何东西,可以查看这个运行 Caribon 作为网络服务的实例

下载

可以使用 git 获取最新版本

$ git clone https://github.com/lise-henry/caribon.git

或者下载其中一个稳定(大致)的 版本

(如果您只计划将 Caribon 作为您的 Rust 程序的库来使用,您不需要过于担心下载和构建,只需在您的 Cargo.toml 文件中添加 caribon = "*" 即可。)

构建

您需要 Rust 和 Cargo,请参阅它们的 安装说明。然后

$cargo build

应该可以完成工作,尽管您也可以直接运行 cargo build --release。然后您可以运行 caribon,通过以下方式

$cargo run --发布

或者直接执行二进制文件(在 target/debugtarget/release 中)

$target/release/caribon

安装

如果您有最新的 Cargo 版本,您可以使用

$cargo install caribon

(对于 crates.io 上的最新版本,或者

$cargo install --githttps://github.com/lise-henry/caribon

对于 GitHub 上的最新版本)

这将下载、构建和安装 Caribon。

Cargo 运行

如果您不想安装 Caribon,cargo run 可能是最简单的方法。请注意,但是,命令行参数必须以 -- 开头,以便 cargo 将它们传递给二进制文件

$cargo run ----input=some_text.txt

此外,请注意,默认情况下,cargo run 会以调试模式构建和运行程序,这会比较慢。对于小文件来说这不是问题,但如果您计划检测小说中的重复内容,使用CPU密集型特性(例如模糊字符串匹配,见下文),则可能希望使用 --release

$ cargo run --release -- --input=big_file.html --output=output_big_file.html

示例

以下是一个 示例,展示了如何使用本README(之前版本)的HTML输出,通过以下命令获得

$caribon --语言=英语 --输入=README.html --输出=example.html --模糊=0.5

(注意,--fuzzy=0.5,虽然有用,可以展示模糊字符串匹配确实可行,但不是一个明智的参数,因为它相当高(单词只需50%相似即可被视为相同,例如将 justrust 匹配)。在实际应用中,建议使用更低的值。)

以下是一个 示例,显示终端中的 README.md 中的重复内容,使用以下命令

$caribon --语言=英语 --输入=README.md --模糊=0.5 | 更多

example

虽然将输出到终端对于小文件可能很有用,但HTML输出会提供更有用的结果,因为高亮显示一个单词将显示其其他出现位置。

选项

Caribon 提供了一系列选项。以下是其中一些选项的解释,从最常用到最复杂的

语言

  • --language=[english|french|spanish|...] 指定输入文件的语言。这很重要有两个原因。第一个原因是 Caribon 在内部使用一个词干库,它可以检测到从同一词干派生的单词,例如 "eats"、"eat" 和 "eating" 将被视为同一单词。有关此词干库如何工作的更多信息,请参阅 Snowball 项目网站。第二个原因是对于某些语言(目前仅为法语和英语),Caribon 提供了一个默认的单词列表,用于重复计数时忽略(例如,在英语中 "it"、"a" 等等都在其中)以避免结果文件杂乱。可以使用 "no_stemmer" 替代语言来禁用词干。这并不真的建议,但如果您想尝试在未实现的语言上使用 Caribon,则可能很有用。
  • --list-languages 打印由词干库支持的语种列表。

输入和输出

  • --input=[file] 指定输入文件。默认情况下为 stdin,这意味着您需要直接输入文本,并以 control-D 结束。如果 file 是一个不存在的文件,则程序会终止。
  • --output=[file] 指定输出文件。默认情况下为 stdout,将结果打印到终端。

输入和输出文件名的扩展名决定了输入和输出格式,例如,如果您传递 --input=text.html --output=result.html,Caribon 将推断内容是 HTML,并且必须以 HTML 格式输出(因此 $ caribon < input.html > output.html 不等同于 $ caribon --input=input.html --output=output.html:在前者的情况下,Caribon 将输入视为原始文本,并以 终端 格式输出(见下文),而在后者中,它将理解这两个文件都是 HTML)。

可以通过指定以下内容来覆盖此行为:

  • --input-format=[text|html]
  • --output-format=[terminal|html|markdown].

关于 终端 输出格式的说明:它被设计为将文本打印到终端,通过使用 UNIX 终端特殊字符下划线和着色一些单词(见上截图)。因此,它仅在未给出输出文件名且 Caribon 打印到标准输出时激活,HTML 输出是大多数情况下的默认设置。

文本统计

  • --print-stats,如果传递给 Caribon,还将在标准输出上显示输入文本的一些统计信息。

阈值和最大距离

Caribon 最有用的算法是本地重复检测。它检测在给定单词间隔内单词是否重复。此间隔由

  • --max-distance=[value](当前默认值是 50)确定。

因此,如果 max-distance 为 50,并且单词 'foo' 在此间隔内出现两次,则每次出现的重复值都为 2。如果 'foo' 在第二个出现后的 50 个单词间隔内第三次重复,则这些出现的重复值都为 3。(如果之后有超过 50 个单词没有出现 'foo',并且 'foo' 再次出现,则最新出现的值将重置为 1)。

当单词的“重复值”高于阈值时,单词会被下划线标出,该阈值可以通过

  • --threshold=[value] 设置。默认值是 1.9,因此单词在重复两次后就会被下划线标出。如果您将阈值更改为,例如,2.5,则单词必须重复三次(本地)才能被下划线标出。

(为什么阈值使用浮点值而不是整数?因为本地重复检测器会根据重复的“严重程度”以不同颜色(绿色、橙色和红色)下划线标出单词。因此,将阈值设置为 1.011.99 不会改变哪些单词被下划线标出,但第一种情况下单词更快地出现在橙色或红色中。)

模糊字符串匹配

Caribon 使用一个词干库来检测属于同一“家族”的单词。结果发现,此算法并不总是足够,尤其是当存在拼写错误时(例如,“higlight”和“highlight”可能应该被认为是重复的,即使第一个拼写有误)。为了解决这个问题,有激活模糊字符串匹配的选项。

  • fuzzy=[value],其中值是一个介于0.0和1.0之间的数字,它表示两个单词之间的“差异”最大值,直到它们不再相同:0.2的值意味着两个单词最多只能“差异20%”才被视为相同。

该算法内部使用Levenshtein距离(以及更具体的是Florian Ebelling的Rust实现),通过估计将一个字符串转换为另一个字符串所需的插入、删除和排列次数来计算两个字符串之间的距离。例如,“dog”和“dogs”的距离为1,而“dog”和“cat”的距离为3。然后将此值除以匹配字符串的长度,当此值小于给定的--fuzzy=值时,两个字符串被认为是“相同”(或至少是重复)。

例如,使用--fuzzy=0.2,"highlight"和"higlight"之间的“差异”估计为1/9(Levenshtein距离为1,只需要一次删除就可以从第一个转换为第二个,除以"highlight"的长度,9),因此它将被视为重复。"Just"和"Rust"之间的“差异”为1/4,所以不会被考虑为重复。

模糊匹配实用,但不应将其设置得过高,否则会有很多误报。经验表明,0.20.25是一个不错的选择。

模糊匹配的缺点是它需要更多的CPU资源。Caribon仍然可以运行得相当快(例如,在启用模糊字符串匹配的情况下检测整篇小说的重复内容不到一秒),但它仅用于局部重复,而不是全局重复(见下文)。

全局重复

默认情况下,Caribon仅检测小于max-distance单词间隔的局部重复。然而,可以通过以下方式激活全局重复检测:

  • --global-threshold=[value],其中value是一个介于0.0和1.0之间的数字。

在这种情况下,如果一个单词的相对出现次数高于全局阈值(即使在一个max-distance范围内从未重复过),则该单词将被视为重复。即如果将global-threshold设置为0.01,则如果一个单词在文档中占总单词数的1%以上,它将被突出显示(蓝色)。

忽略的单词

一些单词,如"a"或"the",不可避免地会重复很多次,而且将它们视为重复没有太大意义。因此,忽略一些单词很有用。Caribon为英语和法语提供了默认列表,但在所有情况下都可以使用以下方式提供自己的列表:

  • --ignore="常见单词列表".

此列表必须由空格或逗号(实际上,可以是任何非字母字符)分隔,并且必须用引号括起来。此列表替代Caribon提供的默认列表(至少对于英语和法语)。如果您想要添加单词到该列表而不是替换它,请使用:

  • --add-ignored="更多忽略单词列表"

忽略单词的另一种方法是:

  • --ignore-proper=[true|false](默认为false)

如果设置为true,Caribon将尝试忽略专有名词。也就是说,如果一个单词以大写字母开头且不在句子的开头,则它不会计入重复。

Caribon 可以作为一个 Rust 库使用。文档可在此处找到;为了确保下载的代码对应的文档版本,您也可以使用以下命令生成:cargo doc

Caribon 库也可在Crates.io找到,允许您轻松地在任何 Cargo 项目中使用它:只需在 Cargo.toml 文件的依赖部分添加

caribon= "0.7"

Caribon-server

如果您不喜欢命令行界面,可以查看Caribon-server,它将 Caribon 作为 Web 服务运行(使用Iron 框架)。关于运行实例的详细信息,请参阅此处

当前功能

  • 内置了法语和英语的忽略词列表(重复次数不重要的常见词),尽管它们并不完整。
  • 支持 Snowball(《http://snowball.tartarus.org/》)项目支持的语言的词干提取。
  • 此外(因为词干提取算法并不总是完美的,有时您会犯拼写错误),支持模糊字符串匹配(基于 Levenhstein 距离)。
  • 本地和全局计数重复。
  • 检测输入中的 HTML 标签。通常对 HTML 片段或完整 HTML 页面都有效。
  • 将检测到的重复内容输出到 HTML 文件(最有用的选项)、直接输出到终端或 Markdown 文件(信息较少)。

变更日志

请参阅此处。.

许可证

Caribon 根据GNU Lesser General Public License,版本 2.1 或(方便起见)任何后续版本进行许可。

致谢

Caribon 由 Élisabeth Henry 编写,电子邮件为 <liz.henry at ouvaton.org>

本软件使用了(Rust 绑定)由 Dr Martin Porter 编写的C 词干提取库,许可证为 BSD 许可证。

它还使用了由 Florian Ebelling 编写的 Levenshtein 距离的 Rust 实现Rust implementation,许可证为 Apache 2.0 许可证。

待办事项

  • 使颜色高亮更可配置
  • 完成内置的忽略词列表,并为其他语言提供(目前只有法语和英语);
  • 提供检测表达式重复的算法,而不仅仅是单个单词的重复;
  • 使库可以从 C(以及其他语言,如 Rust)调用;
  • 增强文档并添加测试。

程序

  • 添加选项以选择高亮颜色
  • 找到更好的默认值?
  • 为程序和库创建不同的存储库?
  • 添加带有 GUI(Gtk+?)的变体?

依赖项

~640KB
~17K SLoC