from __future__ import annotations from typing import List, Dict, Optional import httpx from app.config import settings class SearxngClient: """封装 SearxNG 简单搜索接口。""" def __init__(self) -> None: self.base_url: Optional[str] = getattr(settings, "searxng_base_url", None) self.token: Optional[str] = getattr(settings, "searxng_api_token", None) def search(self, query: str, *, limit: int = 5, categories: str = "general") -> List[Dict[str, str]]: """返回精简的搜索结果列表。""" if not self.base_url: return [] params = { "q": query, "format": "json", "engines": "", "language": "zh-CN", "categories": categories, "limit": limit, } headers = {} if self.token: headers["Authorization"] = f"Token {self.token}" try: resp = httpx.get( self.base_url.rstrip("/") + "/search", params=params, headers=headers, timeout=10.0, ) resp.raise_for_status() data = resp.json() except Exception: return [] results = [] for item in data.get("results", [])[:limit]: title = item.get("title") or "" content = item.get("content") or "" url = item.get("url") or "" if not url: continue results.append( { "title": title, "snippet": content, "url": url, } ) return results searxng_client = SearxngClient()