← На главную

Метапоисковик на Rust опрашивает DuckDuckGo, Brave, Startpage и Yahoo

03.08.2026 16:41 · hackernews

metadata-search-engine-rs — метапоисковик в стиле SearXNG на Rust. Запрос приходит на GET /search?q=<query> и параллельно уходит в DuckDuckGo, Brave, Startpage и Yahoo через reqwest. Ответы разбираются с помощью scraper: это CSS-селекторы поверх html5ever от Mozilla. Результаты дедуплицируются по нормализованному URL: вырезаются tracking-параметры, убираются локальные префиксы, сортируются query-параметры. Дубликаты склеиваются и получают оценку по RRF — score = Σ 1/(60 + rank) по всем движкам. Страница, которую вернули несколько источников, поднимается выше. Топ отдаётся как JSON.

Подключить просто: cargo add metadata-search-engine-rs, либо вписать зависимость в Cargo.toml. Если нужен сервер, склонируйте репозиторий, соберите через cargo build --release и запустите с PORT=8080 MAX_RESULTS=20 cargo run --release. В коде можно работать и с отдельными движками: например, создать DuckDuckGoEngine с Arc<reqwest::Client> и вызвать search("rust programming", 5). Чтобы опросить все движки сразу, используйте query_all_engines и aggregate: successes вернёт результаты, failures — ошибки по каждому движку. Можно ограничиться парой источников, собрав Vec<Arc<dyn SearchEngine>> из DuckDuckGoEngine и BraveEngine.

Готовый сервер отвечает на /health и /search?q=rust. Ответ JSON содержит query, results (title, url, snippet, engines, score), engines_queried и engines_failed. Ошибки тоже аккуратные: нет q — 400 с сообщением, пустой q — 400, все движки упали — 503.

Тесты: cargo test прогоняет unit-тесты, можно точечно запускать normalizer, aggregator, engines::duckduckgo, engines::brave, engines::startpage, engines::yahoo, server::handlers. Live-тесты помечены #[ignore], в CI не выполняются, для них нужен интернет. Их запускают вручную через cargo test -- --ignored test_live, чтобы проверить, что HTML-селекторы по-прежнему работают на живых сайтах.

Есть и TUI на ratatui, он поставляется отдельным crate, а код доступен на GitHub. Новый движок добавить легко: создайте src/engines/<name>.rs, объявите структуру с Arc<reqwest::Client>, реализуйте трейт SearchEngine — методы name и search, возвращающий BoxFuture<Result<Vec<SearchResult>, EngineError>>. Осталось подключить модуль в engines/mod.rs и main.rs.

Читать оригинал →