autolink-java:基于 Java 的链接提取库项目

Java library to extract links (URLs, email addresses) from plain text; fast, small and smart

分支7Tags14
文件最后提交记录最后更新时间
1 年前
10 年前
1 年前
5 年前
10 年前
9 年前
1 年前
7 年前
11 年前
1 年前
1 年前

autolink-java

用于从纯文本中提取链接(如 URL 和电子邮件地址)的 Java 库。 它能智能判断链接的结束位置,例如处理尾随的标点符号。

ci Coverage status Maven Central status

简介

您可能会想:“我需要一个库来做这个吗?我可以为此编写一个正则表达式!” 让我们看几个例子:

  • 在文本 https://example.com/. 中,链接不应包含尾随的句点
  • https://example.com/, 不应包含尾随的逗号
  • (https://example.com/) 不应包含括号

看起来足够简单。但我们还有以下这些情况:

  • https://en.wikipedia.org/wiki/Link_(The_Legend_of_Zelda) 应包含尾随的括号
  • https://üñîçøðé.com/ä 应支持 Unicode(包括表情符号和 Punycode)
  • <https://example.com/> 不应包含尖括号

此库在上述情况以及更多其他情况下的表现符合您的预期。 它通过有限的回溯对输入文本进行一次解析。

感谢 Rinku 提供的灵感。

使用方法

此库支持 Java 11 或更高版本。它可在 Android 上运行(最低 API 级别 19)。它没有外部依赖项。

Maven 坐标 (有关其他构建系统,请参见 此处 ):

<dependency>
    <groupId>org.nibor.autolink</groupId>
    <artifactId>autolink</artifactId>
    <version>0.12.0</version>
</dependency>

提取链接:

import org.nibor.autolink.*;

var input = "two links: https://test.com and https://example.com";
var linkExtractor = LinkExtractor.builder()
        .linkTypes(EnumSet.of(LinkType.URL)) // limit to URLs
        .build();
var links = new ArrayList<>();
for (var span : linkExtractor.extractLinks(input)) {
    var link = input.substring(span.getBeginIndex(), span.getEndIndex());
    links.add(link);
}

links;  // List.of("https://test.com", "https://example.com")

请注意,默认情况下会提取所有受支持的链接类型。如果您只对特定类型感兴趣,可以使用 linkTypes 方法进行筛选。

上述操作会返回所有链接。有时您需要做的是遍历某些输入内容,处理链接并保留周围文本。针对这种情况,有一个 extractSpans 方法。

以下是使用该方法将文本转换为 HTML 并将 URL 包装在 <a> 标签中的示例(使用 owasp-java-encoder 进行转义):

import org.nibor.autolink.*;
import org.owasp.encoder.Encode;

String input = "wow http://test.com such linked";
LinkExtractor linkExtractor = LinkExtractor.builder()
        .linkTypes(EnumSet.of(LinkType.URL)) // limit to URLs
        .build();
Iterable<Span> spans = linkExtractor.extractSpans(input);

StringBuilder sb = new StringBuilder();
for (Span span : spans) {
    String text = input.substring(span.getBeginIndex(), span.getEndIndex());
    if (span instanceof LinkSpan) {
        // span is a URL
        sb.append("<a href=\"");
        sb.append(Encode.forHtmlAttribute(text));
        sb.append("\">");
        sb.append(Encode.forHtml(text));
        sb.append("</a>");
    } else {
        // span is plain text before/after link
        sb.append(Encode.forHtml(text));
    }
}

sb.toString();  // "wow <a href=\"http://test.com\">http://test.com</a> such linked"

请注意,这里假设输入内容为纯文本,而非 HTML。 另请参见下方的“不支持的功能”部分。

功能特性

URL 提取

提取 scheme://example 形式的 URL,支持任何潜在有效的协议方案。 example:test 这类 URI 不会被匹配(未来可能会作为可选项添加)。如果只需允许特定协议方案,可对结果进行过滤。 (注意,协议方案中可包含点号,因此 foo.http://example 会被识别为单个链接。)

内置启发式规则,避免包含标点符号和非平衡括号等尾随分隔符,示例如下。

支持国际化域名(IDN)。请注意,不会对国际化域名进行验证,因此可能会匹配到无效的 URL。

输入示例及链接提取结果:

此功能使用 LinkType.URL,测试用例参见 此处

WWW 链接提取

提取 www.example.com 这类链接。它们需以 www. 开头,但无需 scheme://。链接结尾的检测方式与 URL 采用相同的启发式规则。

示例:

不支持的情况:

  • 大写形式的 www,例如 WWW.example.comwWw.example.com
  • w 的数量过多或过少,例如 wwww.example.com

域名必须至少包含 3 个部分,因此 www.com 无效,但 www.something.co.uk 有效。

此功能使用 LinkType.WWW,测试用例参见 此处

电子邮件地址提取

提取诸如 foo@example.com 之类的电子邮件。支持匹配国际电子邮件地址,但不验证域名(可能会匹配过多内容)。

示例:

不支持的情况:

  • 带引号的本地部分,例如 "this is sparta"@example.com
  • 地址字面量,例如 foo@[127.0.0.1]

请注意,域名必须至少包含一个点(例如 foo@com 不会被匹配),除非禁用 emailDomainMustHaveDot 选项。

为此,请使用 LinkType.EMAIL,测试用例详见 此处

本库不具备的功能

本库特意不支持 HTML 识别。如果支持 HTML,就需要依赖 HTML 解析器和渲染器。 考虑以下输入:

HTML that contains <a href="https://one.example">links</a> but also plain URLs like https://two.example.

如果您想将纯文本链接转换为 a 元素,同时保持已有的链接不变,建议您:

  1. 使用 HTML 解析器库解析 HTML
  2. 遍历生成的 DOM,并使用 autolink-java 仅在文本节点中查找链接
  3. 将这些链接转换为 a 元素
  4. 将 DOM 重新渲染为 HTML

贡献

详见 CONTRIBUTING.md 文件。

许可证

版权所有 (c) 2015,Robin Stocker 及其他贡献者,详见 Git 历史记录

采用 MIT 许可证,详见 LICENSE 文件。

项目介绍

Java library to extract links (URLs, email addresses) from plain text; fast, small and smart

定制我的领域