开发者生态
evening
Rust 中的 SearXNG
2026-08-03
1 阅读
约9分钟阅读
dluuuu
字号:
metadata-search-engine-rs 一个用 Rust 编写的 SearXNG 风格的元数据搜索引擎。同时将查询扇出到多个搜索引擎,抓取 HTML 结果,按规范化 URL 进行重复数据删除,并使用倒数排名融合 (RRF) 进行排名。工作原理 搜索请求到达 GET /search?q= 查询通过 reqwest 同时发送到 DuckDuckGo、Brave、Startpage 和 Yahoo 每个引擎都使用 scraper 解析 HTML 响应(Mozilla 的 html5ever 上的 CSS 选择器) 结果通过规范化 URL 进行重复数据删除(跟踪参数被剥离,区域设置前缀被删除,查询参数被排序) 重复的 URL 被合并并使用 RRF 进行评分(score = Σ 1/(60 + 排名) 跨引擎) — 多个引擎返回的页面排名更高 最上面的结果以 JSON 形式返回 要求 Rust 1.75+ Cargo 安装 作为库 Cargo 添加metadata-search-engine-rs 或手动添加到 Cargo.toml : [ dependency ]metadata-search-engine-rs = " 0.1 " 作为服务器(来自源) git clone https://github.com/MikeLuu99/searxng-rust cd metadata-search-engine-rscargobuild --release 运行cargorun PORT=8080 MAX_RESULTS=20cargorun --release 启用调试日志记录:RUST_LOG=debugcargorun 示例添加到您的Cargo.toml中: [dependency]metadata-search-engine-rs = "0.1"tokio={version="1",features=["full"]} 查询单个引擎使用std::sync::Arc;使用metadata_search_engine_rs::engines::{DuckDuckGoEngine,SearchEngine,build_http_client}; # [ tokio :: main ] async fn main ( ) -> 无论如何 :: Result < ( ) > { let client = Arc :: new ( build_http_client ( ) ? ) ;让引擎 = DuckDuckGoEngine { 客户端 } ;让结果=引擎。搜索(“Rust 编程”,5)。等待? ; for r in results { println ! ( "{} \n {}" , r . title , r . url ) ; } Ok ( ( ) ) } 扇出到所有引擎并使用 std::sync::Arc 获得 RRF 排名结果;使用metadata_search_engine_rs :: { aggregator :: {aggregate,query_all_engines},engines :: {BraveEngine,DuckDuckGoEngine,SearchEngine,StartpageEngine,YahooEngine,build_http_client},}; # [ tokio :: main ] async fn main ( ) -> 无论如何 :: Result < ( ) > { let client = Arc :: new ( build_http_client ( ) ? ) ;让引擎:Vec>=vec! [Arc::new(DuckDuckGoEngine{客户端:Arc::克隆(&客户端)}),Arc::new(BraveEngine{客户端:Arc::克隆(&客户端)}),Arc::new(StartpageEngine{客户端:Arc::克隆(&客户端)}),Arc::new(YahooEngine{客户端:Arc::克隆(&客户端)}),]; let ( 成功 , 失败 ) = query_all_engines ( & 引擎 , "rust 编程" , 10 ) 。等待; for ( 名称 , 错误 ) in & 失败 { eprintln ! (“引擎{name}失败:{err}”);让结果=聚合(成功,10); for r in & results { println ! ( "[{:.3}] ({}) {}" , r . 分数 , r . 引擎 . join ( ", " ) , r . 标题 ) ;打印! ("{}", r.url); } Ok ( ( ) ) } 仅使用特定引擎使用 std::sync::Arc ;使用metadata_search_engine_rs :: { aggregator :: {aggregate,query_all_engines},engines :: {BraveEngine,DuckDuckGoEngine,SearchEngine,build_http_client},}; # [ tokio :: main ] async fn main ( ) -> 无论如何 :: Result < ( ) > { let client = Arc :: new ( build_http_client ( ) ? ) ;让引擎:Vec>=vec! [ Arc::new(DuckDuckGoEngine{ 客户端:Arc::clone(&客户端)}), Arc::new(BraveEngine{客户端:Arc::clone(&客户端)}),]; let ( successes , _ ) = query_all_engines ( &Engines , "tokio 异步 rust" , 5 ) 。等待; for r inaggregate ( successes , 5 ) { println ! ( "{} — {}" , r . title , r . url ) ; if let Some(snippet) = r 。片段 { 打印! (“{片段}”); } } Ok ( ( ) ) } API GET /health curl http://localhost:3000/health { "status" : " ok " } GET /search?q=curl " http://localhost:3000/search?q=rust " { "query" : " rust " , "results" : [ { "title" : " Rust 编程语言 " , "url" : " https://rust-lang.org/ ", "snippet" : "一种让每个人都能构建可靠、高效软件的语言", "engines" : [ " duckduckgo " ,
这篇文章对您有帮助吗?
订阅66必读
每日精选科技资讯,直达你的邮箱