你是否需要一个免费的、无请求次数限制的 Web 搜索 API?本文教你用开源项目 SearXNG 在自有服务器上部署一个支持 JSON 输出的搜索引擎"中转站",完美替代 Google/Bing 付费 API,每日数千次请求稳定运行。
🧐 为什么需要自建搜索 API?
在做内容聚合、信息检索或 AI 应用时,经常需要调用搜索引擎获取网页结果。但商业 API(Google Custom Search、Bing Search)要么免费额度极低(每天 100 次),要么即将停止服务(Bing Search API 2025 年关闭),而直接爬虫又容易被封 IP。
SearXNG 是完美的解决方案:
-
完全免费:开源,无使用次数限制,成本只取决于你的服务器。
-
元搜索引擎:同时聚合 Google、Bing、DuckDuckGo 等 70+ 引擎,自动去重。
-
支持 JSON API :原生提供
format=json,程序调用非常方便。 -
隐私友好:不记录日志,不追踪用户。
-
高度可控:可自由选择搜索引擎、限速、部署反向代理等。
🛠️ 环境要求
-
操作系统:Ubuntu 24.04(其他 Linux 发行版同样适用)
-
配置:1 核 CPU + 1 GB 内存 即可(日均 1k~3k 次请求无压力)
-
网络:服务器需能够正常访问 Google、Bing 等搜索引擎(海外 VPS 最佳)
-
工具:Docker 和 Docker Compose(脚本会自动安装)
🚀 一键部署
将以下脚本保存为 install.sh,用 root 用户执行即可。一键完成 Docker 安装、配置文件生成和容器启动。
#!/bin/bash
set -e
# ---------- 配置变量(请修改为你的实际信息)----------
SEARXNG_DIR="/data/searxng" # 部署目录
SERVER_IP="your-server-ip" # 替换为你的服务器公网IP或域名
# ----------------------------------------------------
SECRET_KEY=$(openssl rand -hex 32)
# 安装 Docker(如已安装则跳过)
if ! command -v docker &> /dev/null; then
echo "正在安装 Docker..."
curl -fsSL https://get.docker.com | bash
systemctl enable docker --now
fi
# 创建目录结构
mkdir -p "${SEARXNG_DIR}"/{searxng,data/redis,data/searxng}
# 生成 docker-compose.yml
cat > "${SEARXNG_DIR}/docker-compose.yml" <<EOF
services:
redis:
image: valkey/valkey:8-alpine
container_name: searxng-redis
restart: unless-stopped
command: valkey-server --save 30 1 --loglevel warning
networks:
- searxng-network
volumes:
- ./data/redis:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 3
searxng:
image: searxng/searxng:latest
container_name: searxng
restart: unless-stopped
depends_on:
redis:
condition: service_healthy
networks:
- searxng-network
ports:
- "8002:8080" # 宿主机端口:容器内端口(容器内固定为8080)
volumes:
- ./searxng/settings.yml:/etc/searxng/settings.yml:ro
- ./data/searxng:/var/cache/searxng
environment:
- SEARXNG_BASE_URL=http://${SERVER_IP}:8002/ # 末尾斜杠不可省略
- INSTANCE_NAME=my-searxng-api
networks:
searxng-network:
driver: bridge
EOF
# 生成 settings.yml(开启 JSON API,关闭内置限速)
cat > "${SEARXNG_DIR}/searxng/settings.yml" <<EOF
use_default_settings: true
general:
instance_name: "SearXNG API"
search:
safe_search: 0
formats:
- html
- json # 必须保留 json,否则 API 返回 403
results_per_page: 10
server:
secret_key: "${SECRET_KEY}"
limiter: false # 关闭自限速,由调用程序自行控制频率
image_proxy: false
bind_address: "0.0.0.0"
port: 8080
ui:
default_theme: simple
# 此处不限定搜索引擎,可在 API 请求时通过 engines 参数动态指定
outgoing:
request_timeout: 10.0
max_request_timeout: 15.0
useragent_suffix: ""
pool_connections: 20
pool_maxsize: 5
EOF
# 启动服务
cd "${SEARXNG_DIR}"
docker compose up -d
sleep 5
echo "部署完成!"
echo "Web 界面: http://${SERVER_IP}:8002"
echo "API 端点: http://${SERVER_IP}:8002/search?q=关键词&format=json"
执行方式:
bash
复制
下载
# 赋予执行权限
chmod +x install.sh
# 运行(必须 root 权限)
sudo bash install.sh
📌 如果脚本执行时出现
\r相关错误,说明文件包含 Windows 换行符。执行sed -i 's/\r$//' install.sh修复后再运行。
⚙️ 配置要点解读
-
端口映射 :
docker-compose.yml中ports: "8002:8080"表示将宿主机的8002端口映射到容器内的8080端口(SearXNG 内部固定监听 8080)。你可以根据需求修改宿主机端口。 -
BASE_URL :环境变量
SEARXNG_BASE_URL必须设置为外部可访问的地址,末尾斜杠/不能省略,否则返回的链接可能出错。 -
JSON 输出 :
settings.yml中的search.formats必须包含json,否则 API 请求会返回403 Forbidden。 -
限速策略 :我们已将
server.limiter设为false,关闭 SearXNG 自身的限流器。每日数千次请求的安全由调用方控制频率(建议间隔 ≥ 1 秒)来保证,避免给上游引擎造成过大压力。 -
引擎选择 :我们没有在配置中限定搜索引擎,而是推荐在 API 请求时通过
engines=google,bing参数动态指定,灵活且不易因配置语法变化而报错。
🧪 测试验证
1. 检查容器状态
bash
复制
下载
docker ps | grep searxng
两个容器(searxng 和 searxng-redis)状态均应为 Up。
2. 命令行测试 API
bash
# 基本查询(注意关键词中的空格需 URL 编码,此处用 --data-urlencode 自动处理)
curl -G "http://localhost:8002/search" \
--data-urlencode "q=hello world" \
--data-urlencode "format=json" \
--data-urlencode "engines=google,bing"
返回 JSON 数据表示成功。若返回空或错误,请检查 docker compose logs searxng 查看日志。
3. 浏览器验证
访问 http://your-server-ip:8002,能看到 SearXNG 的搜索页面,说明前端正常。
🐍 编程调用示例 (Python)
import requests
import time
def search(query, engines="google,bing", language="zh-CN"):
params = {
"q": query,
"format": "json",
"engines": engines,
"language": language
}
resp = requests.get("http://your-server-ip:8002/search", params=params)
resp.raise_for_status()
return resp.json()
# 示例:查询 ISBN
data = search("9789575037109")
for item in data.get("results", []):
print(item["title"], item["url"])
time.sleep(1) # 控制请求间隔,避免被上游限制
请求间隔建议:每日 1k~3k 次请求,保持至少 1 秒间隔即可安全运行。若服务器 IP 信誉良好,甚至可适当加快,但强烈不建议低于 0.5 秒。
🔧 常见问题与排错
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
容器状态 Restarting |
settings.yml 格式错误 |
检查 YAML 缩进,或使用默认配置先启动再逐步调整 |
端口监听不到 ss -tlnp 无输出 |
端口映射错误,如写成 8002:8002 |
修改为 8002:8080,重启容器 |
| API 返回 403 | formats 中缺少 json |
在 settings.yml 的 search.formats 列表中添加 - json |
curl 报错 Malformed input |
URL 中包含未编码的空格或特殊字符 | 使用 --data-urlencode 或对空格编码为 %20 |
| Bing 返回大量不相关结果 | Bing 对某些查询的语义理解偏差 | 尝试只使用 engines=google,或加上 language=zh-CN 参数 |
容器日志 TypeError: string indices... |
engines 配置使用了不兼容的 keep_only 语法 |
移除配置中的引擎限制,改用 API 参数动态指定 |
🚀 进阶优化
-
反向代理与 HTTPS :可以使用 Caddy 或 Nginx 反代
localhost:8002,添加 SSL 证书,对外仅暴露 443 端口。 -
防火墙 :建议限制
8002端口仅允许本地或特定 IP 访问,避免被外部扫描滥用。 -
备用引擎 :除了 Google/Bing,建议在请求中加入
duckduckgo作为备用(engines=google,bing,duckduckgo),当一个引擎失效时依然能获取结果。 -
监控与日志 :
docker compose logs -f searxng可实时查看请求日志。
🎉 总结
至此,你已经拥有了一个完全免费、无调用次数限制、输出 JSON 的搜索 API。无论是做个人项目还是小型商业应用,这套方案都能长期稳定运行。如果你觉得有用,欢迎分享给更多需要的人!