Rust超链接解析库parse-hyperlinks的使用,高效提取与处理文本中的URL链接

Rust超链接解析库parse-hyperlinks的使用,高效提取与处理文本中的URL链接

Parse-hyperlinks是一个用Nom编写的解析器库,用于识别Markdown、reStructuredText、Asciidoc和HTML格式文本输入中的超链接和链接引用定义。

Cargo Documentation License

该库实现了CommonMark规范0.30、reStructuredText标记规范(修订版8571,日期2020-10-28)、Asciidoctor用户手册第26章(日期2020-12-03)和HTML 5.2第4.5节中的规范。

Parse-Hyperlinks输入约定

  1. 所有输入都是UTF-8编码的
  2. 输入文本根据上述标记语言规范之一进行格式化

HTML文档的额外输入约定

  1. HTML文档中绝对URL中的字符&<>"必须进行HTML转义编码
  2. UTF-8编码的HTML文档中的相对URL不需要HTML转义编码
  3. 相对URL不能以方案开头(如http:
  4. URL可以同时进行HTML转义编码和百分比编码

完整示例代码

以下是内容中提供的示例:

use parse_hyperlinks::{extract_links, Link};

fn main() {
    // 示例文本包含多种格式的链接
    let text = r#"
这是一个包含多种链接格式的文本:

1. Markdown内联链接: [Rust官网](https://www.rust-lang.org)
2. Markdown自动链接: <https://crates.io>
3. HTML链接: <a href="https://doc.rust-lang.org">Rust文档</a>
4. 纯文本URL: 访问https://github.com/rust-lang
    "#;

    // 提取所有链接
    let links = extract_links(text);
    
    println!("在文本中找到的链接:");
    for (i, link) in links.iter().enumerate() {
        println!("{}. {} -> {}", i + 1, link.text, link.destination);
    }
    
    // 处理特定类型的链接
    let markdown_links: Vec<&Link> = links.iter()
        .filter(|l| l.format == "markdown")
        .collect();
        
    println!("\nMarkdown链接:");
    for link in markdown_links {
        println!("- {}: {}", link.text, link.destination);
    }
}

扩展示例代码

以下是一个更完整的示例,展示如何处理不同类型的链接并输出统计信息:

use parse_hyperlinks::{extract_links, Link};

fn main() {
    // 包含多种格式的混合文本
    let text = r#"
# 示例文档

## 段落1
这是一个[Markdown链接](https://example.com),以及一个HTML链接:
<a href="https://html.example.com">HTML示例</a>。

## 段落2
自动链接: <https://auto.example.com>
纯文本URL: 访问https://text.example.com了解更多。

## 段落3
参考式链接: [参考链接][id]

[id]: https://reference.example.com "参考标题"
    "#;

    // 提取所有链接
    let links = extract_links(text);
    
    // 统计不同类型链接的数量
    let mut markdown_count = 0;
    let mut html_count = 0;
    let mut auto_count = 0;
    let mut text_count = 0;
    
    for link in &links {
        match link.format.as_str() {
            "markdown" => markdown_count += 1,
            "html" => html_count += 1,
            "auto" => auto_count += 1,
            "text" => text_count += 1,
            _ => (),
        }
    }
    
    println!("链接统计:");
    println!("- Markdown链接: {}", markdown_count);
    println!("- HTML链接: {}", html_count);
    println!("- 自动链接: {}", auto_count);
    println!("- 纯文本URL: {}", text_count);
    println!("- 总链接数: {}", links.len());
    
    // 输出所有链接详情
    println!("\n链接详情:");
    for (i, link) in links.iter().enumerate() {
        println!("{}. [{}] {} -> {}", 
            i + 1, 
            link.format, 
            link.text, 
            link.destination
        );
    }
}

安装

在项目目录中运行以下Cargo命令:

cargo add parse-hyperlinks

或者在Cargo.toml中添加以下行:

parse-hyperlinks = "0.29.0"

主要功能

  • 支持多种标记语言的链接解析
  • 高效提取文本中的URL
  • 区分不同类型的链接(Markdown、HTML等)
  • 处理转义和编码的URL
  • 轻量级且快速

这个库特别适合需要从混合格式文本中提取和分析链接的应用场景,如文档处理工具、爬虫或内容分析系统。


1 回复

Rust超链接解析库parse-hyperlinks使用指南

parse-hyperlinks是一个高效的Rust库,专门用于从文本中提取和处理URL链接。它提供了简单易用的API,能够快速识别文本中的各种格式的超链接。

功能特性

  • 支持提取HTTP/HTTPS/FTP等常见协议的URL
  • 识别包含在尖括号、引号或纯文本中的链接
  • 高性能的解析算法
  • 可配置的解析选项
  • 支持相对URL的解析(需配合基础URL)

安装方法

在Cargo.toml中添加依赖:

[dependencies]
parse-hyperlinks = "0.3"

基本使用方法

简单提取链接

use parse_hyperlinks::find_links;

fn main() {
    // 示例文本包含多个URL
    let text = "Visit my website at https://example.com or check out https://rust-lang.org";
    
    // 使用find_links函数提取所有链接
    let links = find_links(text);
    
    // 打印找到的所有链接
    for link in links {
        println!("Found link: {}", link.as_str());
    }
}

处理HTML中的链接

use parse_hyperlinks::{find_links, Link};

fn main() {
    // HTML示例文本
    let html = r#"
        <a href="https://example.com/page1">Link 1</a>
        <img src="https://example.com/image.png" alt="Example">
    "#;
    
    // 提取HTML中的链接
    let links = find_links(html);
    
    // 对不同类型的链接进行分类处理
    for link in links {
        match link {
            Link::Url(url) => println!("URL: {}", url),
            Link::Email(email) => println!("Email: {}", email),
        }
    }
}

高级配置选项

use parse_hyperlinks::{LinkFinder, LinkKind};

fn main() {
    let text = "Contact me at user@example.com or visit https://example.com";
    
    // 创建LinkFinder实例
    let mut finder = LinkFinder::new();
    
    // 配置只查找电子邮件地址
    finder.kinds(&[LinkKind::Email]);
    
    // 收集并打印找到的电子邮件
    let links: Vec<_> = finder.links(text).collect();
    println!("Found emails: {:?}", links);
}

处理相对URL

use parse_hyperlinks::{LinkFinder, Url};

fn main() {
    // 基础URL,用于解析相对路径
    let base_url = Url::parse("https://example.com/base/").unwrap();
    let text = "Check out <a href='/about'>About page</a>";
    
    // 创建LinkFinder并设置基础URL
    let mut finder = LinkFinder::new();
    finder.url(&base_url);
    
    // 解析链接并打印绝对URL
    let links = finder.links(text);
    for link in links {
        if let Some(url) = link.as_url() {
            println!("Absolute URL: {}", url);
        }
    }
}

性能提示

use parse_hyperlinks::LinkFinder;

fn main() {
    // 多个文本示例
    let texts = vec![
        "First text with https://link1.com",
        "Second text with https://link2.org",
        "Third text with contact@example.com"
    ];
    
    // 重用LinkFinder实例提高性能
    let mut finder = LinkFinder::new();
    
    // 处理每个文本
    for text in texts {
        let links: Vec<_> = finder.links(text).collect();
        println!("Found {} links in text", links.len());
    }
}

错误处理

use parse_hyperlinks::LinkFinder;
use url::ParseError;

fn main() -> Result<(), ParseError> {
    // 包含无效URL的文本
    let text = "Invalid URL: https://example.com/%%invalid";
    let finder = LinkFinder::new();
    
    // 处理每个链接,区分有效和无效URL
    for link in finder.links(text) {
        match link.as_url() {
            Some(url) => println!("Valid URL: {}", url),
            None => println!("Invalid URL detected: {}", link.as_str()),
        }
    }
    
    Ok(())
}

完整示例代码

下面是一个综合使用parse-hyperlinks库的完整示例:

use parse_hyperlinks::{LinkFinder, LinkKind, Link};
use url::Url;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 示例文本包含各种类型的链接
    let content = r#"
        <html>
            <body>
                <h1>Welcome</h1>
                <p>Visit us at https://example.com</p>
                <a href="/about">About</a>
                <p>Contact: support@example.com</p>
                <img src="logo.png" alt="Logo">
            </body>
        </html>
    "#;
    
    // 设置基础URL用于解析相对路径
    let base_url = Url::parse("https://example.com")?;
    
    // 配置LinkFinder
    let mut finder = LinkFinder::new();
    finder.url(&base_url); // 设置基础URL
    finder.kinds(&[LinkKind::Url, LinkKind::Email]); // 查找URL和电子邮件
    
    // 提取和处理链接
    println!("Extracted links:");
    for link in finder.links(content) {
        match link {
            Link::Url(url) => {
                println!("- URL: {}", url);
            }
            Link::Email(email) => {
                println!("- Email: {}", email);
            }
        }
    }
    
    Ok(())
}

这个完整示例演示了如何:

  1. 处理HTML内容中的链接
  2. 配置LinkFinder查找特定类型的链接
  3. 使用基础URL解析相对路径
  4. 区分处理URL和电子邮件链接
  5. 提供基本的错误处理

parse-hyperlinks库非常适合需要从各种文本内容中提取链接的场景,它的高性能和灵活性使其成为Rust生态中链接处理的优秀选择。

回到顶部