Skip to content
ChouChiu edited this page Sep 23, 2026 · 3 revisions

搜索功能

搜索模块提供跨平台的歌曲检索与歌词获取能力,通过 search feature 控制(默认开启)。

如需纯离线构建,可在依赖中禁用该特性以避免引入 reqwest、tokio 等网络依赖:

[dependencies]
lyrics-helper = { version = "0.5.0", default-features = false }

支持的平台

平台 Searcher 特点与要求
网易云音乐 NeteaseSearcher 先尝试 Web 接口,海外 IP 或被风控(-460)时自动改走 eapi 接口并持久记录该状态
QQ 音乐 QQMusicSearcher 支持公共曲库搜索;歌词接口下发十六进制加密 QRC,自动解密
酷狗音乐 KugouSearcher 支持候选列表搜索;歌词接口下发 Base64 编码的 LRC 文本,自动解码
汽水音乐 SodaMusicSearcher 字节跳动旗下汽水音乐公共检索接口
Musixmatch MusixmatchSearcher 国际歌词源;支持 Android(默认)和桌面版 API(可通过 ApiOptions 配置)
LRCLIB LRCLIBSearcher 开放歌词数据库,无凭据要求,提供逐行同步 LRC 与纯文本歌词
AMLL TTML DB AmllTtmlDbSearcher 社区逐词 TTML 静态库;无远程搜索接口,下载元数据索引后在本地多字段匹配
Apple Music AppleMusicSearcher 需要传入开发者 Bearer Token;仅支持曲目元数据搜索,不提供歌词
Spotify SpotifySearcher 需要传入 Web API 的 Access Token(Bearer);仅支持曲目搜索

Note

网易云音乐、QQ 音乐等国内流媒体平台返回的搜索结果高度依赖网络出口 IP 的地区版权状态(例如海外 IP 通常只能检索到翻唱或无法播放的条目)。在测试或编写自动化逻辑时,避免对具体歌曲的检索结果顺序做严格断言。

基本搜索

搜索最佳匹配曲目

使用 search_for_best_result() 检索并在内部计算打分,返回匹配度最高的一条结果:

use lyrics_helper::models::TrackMetadata;
use lyrics_helper::searchers::netease::NeteaseSearcher;
use lyrics_helper::searchers::search_for_best_result;

#[tokio::main]
async fn main() {
    let mut track = TrackMetadata::new();
    track.title = Some("晴天".to_string());
    track.artist = Some("周杰伦".to_string());
    track.album = Some("叶惠美".to_string());
    track.duration_ms = Some(269000);
    track.ensure_artists();

    match search_for_best_result(&NeteaseSearcher, &track).await {
        Ok(Some(result)) => {
            println!("匹配歌曲: {} - {}", result.title, result.artist());
            println!("匹配等级: {:?}", result.match_type);
            println!("平台 ID: {}", result.id);
        }
        Ok(None) => println!("未找到匹配曲目"),
        Err(err) => eprintln!("搜索请求失败: {err}"),
    }
}

错误约定:

  • Ok(None):请求成功,但没有匹配的歌曲。
  • Err(SearchError):请求失败(网络错误、平台限流、命中验证码或接口异常)。详见搜索类型与高级函数。

多平台并发搜索

所有平台搜索器均实现 Searcher trait:

use lyrics_helper::models::TrackMetadata;
use lyrics_helper::searchers::searcher::Searcher;
use lyrics_helper::searchers::*;

#[tokio::main]
async fn main() {
    let mut track = TrackMetadata::new();
    track.title = Some("Bang Bang".to_string());
    track.artist = Some("Jessie J, Ariana Grande, Nicki Minaj".to_string());
    track.duration_ms = Some(199000);
    track.ensure_artists();

    let platforms: [(&str, &dyn Searcher); 4] = [
        ("网易云", &netease::NeteaseSearcher),
        ("QQ 音乐", &qq_music::QQMusicSearcher),
        ("酷狗", &kugou::KugouSearcher),
        ("LRCLIB", &lrclib::LRCLIBSearcher),
    ];

    for (name, searcher) in platforms {
        match search_for_best_result(searcher, &track).await {
            Ok(Some(best)) => println!("{name}: {} ({:?})", best.title, best.match_type),
            Ok(None) => println!("{name}: 无结果"),
            Err(err) => eprintln!("{name}: 错误 - {err}"),
        }
    }
}

获取歌词

通过搜索得到 SearchResult 后,使用各平台的 providers 客户端获取歌词文本:

use lyrics_helper::models::TrackMetadata;
use lyrics_helper::providers::web::netease;
use lyrics_helper::searchers::netease::NeteaseSearcher;
use lyrics_helper::searchers::search_for_best_result;

#[tokio::main]
async fn main() {
    let mut track = TrackMetadata::new();
    track.title = Some("晴天".to_string());
    track.artist = Some("周杰伦".to_string());
    track.ensure_artists();

    if let Ok(Some(result)) = search_for_best_result(&NeteaseSearcher, &track).await {
        let song_id: i64 = result.id.parse().unwrap_or(0);
        match netease::api::get_lyrics(song_id).await {
            Ok((Some(lrc), translation)) => {
                println!("原文歌词:\n{lrc}");
                if let Some(trans) = translation {
                    println!("翻译歌词:\n{trans}");
                }
            }
            Ok((None, _)) => println!("该歌曲无可用歌词"),
            Err(err) => eprintln!("获取歌词失败: {err}"),
        }
    }
}

AMLL TTML DB

AMLL TTML DB 是一个由社区维护的逐词 TTML 歌词库。其 provider 位于 lyrics_helper::providers::web::amll_ttml_db::api:

函数 说明
search(keyword) 在元数据索引中进行多关键字模糊匹配,返回匹配条目列表(从新到旧)
get_raw_lyrics(file_name) 根据文件名从仓库中拉取原始 TTML 文件文本
get_lyrics(platform, id, format) 根据网易云/QQ 音乐/Apple Music/Spotify 的平台歌曲 ID 获取对应格式歌词(支持 TTML、LRC、YRC、QRC、Lyricify Syllable 等)
set_base_url(url) 切换下载镜像站点(如 BIKONOO_BASE_URL 或 GBCLSTUDIO_BASE_URL),用于改善国内网络访问

使用示例:

use lyrics_helper::providers::web::amll_ttml_db::api::{self, Format, Platform};
use lyrics_helper::{parse, LyricsRawTypes};

#[tokio::main]
async fn main() {
    let entries = api::search("晴天 周杰伦").await.expect("搜索索引失败");
    let Some(entry) = entries.first() else {
        println!("未找到条目");
        return;
    };

    println!("命中条目: {} - {}", entry.title(), entry.artists.join(", "));

    // 1. 获取原始逐词 TTML
    if let Ok(Some(ttml)) = api::get_raw_lyrics(&entry.raw_lyric_file).await {
        if let Some(data) = parse(&ttml, LyricsRawTypes::Ttml) {
            println!("TTML 解析成功,共 {} 行", data.lines.as_ref().map_or(0, Vec::len));
        }
    }

    // 2. 若条目记录了对应网易云 ID,可直接取转换为 LRC 的文本
    if let Some(ncm_id) = entry.ncm_music_ids.first() {
        if let Ok(Some(lrc)) = api::get_lyrics(Platform::Netease, ncm_id, Format::Lrc).await {
            println!("LRC 获取成功,长度 {} 字节", lrc.len());
        }
    }
}

Clone this wiki locally