Google 自定义搜索引擎已关闭新注册,并将于 2027 年 1 月 1 日结束其搜索整个网络功能。如果您的应用程序依赖 CSE 进行网络搜索,则您现在需要一个迁移计划。 Scavio 提供了一种直接替代方案,可通过单个 POST 端点覆盖 Google、Amazon、YouTube、Walmart、Reddit 和 TikTok,每个请求 0.005 美元。本教程将逐步介绍每个步骤:审核您当前的 CSE 使用情况、将 CSE 参数映射到 Scavio 等效参数、更新代码以及验证结果。
前置条件
- 您需要迁移的现有 Google CSE 集成
- 安装了 Python 3.9+ 或 Node.js 18+
- 来自 scavio.dev 的 Scavio API 密钥
- 访问您当前的 CSE API 密钥和搜索引擎 ID
操作指南
步骤 1: 审核您当前的 CSE 使用情况
在迁移之前,记录代码库中的每个 CSE 调用。记录您使用的查询参数、您解析的响应字段以及您每月的请求量。
# Typical Google CSE call you need to replace
import requests
CSE_KEY = 'your-google-api-key'
CSE_ID = 'your-search-engine-id'
def old_cse_search(query: str) -> list:
resp = requests.get('https://www.googleapis.com/customsearch/v1', params={
'key': CSE_KEY, 'cx': CSE_ID, 'q': query, 'num': 10
})
items = resp.json().get('items', [])
return [{'title': i['title'], 'link': i['link'],
'snippet': i.get('snippet', '')} for i in items]
# Document what you actually use from the response
results = old_cse_search('best python frameworks 2026')
for r in results:
print(f"{r['title']} -> {r['link']}")步骤 2: 创建 Scavio 替换函数
将 CSE GET 请求替换为 Scavio POST 请求。响应结构映射清晰:项目变成organic_results,每个结果都有标题、链接和片段字段。
import os, requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def scavio_search(query: str, num: int = 10) -> list:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': num})
resp.raise_for_status()
results = resp.json().get('organic_results', [])
return [{'title': r['title'], 'link': r['link'],
'snippet': r.get('snippet', '')} for r in results]
results = scavio_search('best python frameworks 2026')
for r in results:
print(f"{r['title']} -> {r['link']}")步骤 3: 映射 CSE 特定参数
如果您使用站点限制、日期范围或语言过滤等 CSE 功能,请将它们映射到 Scavio 查询参数或查询语法。
# CSE site restriction -> Scavio query syntax
# Old: params={'siteSearch': 'reddit.com', 'q': query}
# New: prepend site: to query
def search_site(query: str, site: str) -> list:
return scavio_search(f'site:{site} {query}')
# CSE country -> Scavio country_code
def search_country(query: str, country: str = 'us') -> list:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': country, 'num_results': 10})
return resp.json().get('organic_results', [])
# CSE date restrict -> Scavio query syntax
def search_recent(query: str) -> list:
return scavio_search(f'{query} after:2026-01-01')
print('Site search:', len(search_site('python tutorial', 'docs.python.org')))
print('Country search:', len(search_country('AI news', 'gb')))
print('Recent search:', len(search_recent('AI frameworks')))步骤 4: 构建零停机交换的兼容性包装器
创建与确切的 CSE 响应格式匹配的包装器,因此下游代码无需更改。这使您可以在不接触消费者的情况下交换后端。
def cse_compatible_search(query: str, **kwargs) -> dict:
"""Drop-in replacement that returns CSE-format response."""
num = kwargs.get('num', 10)
results = scavio_search(query, num=num)
# Return CSE-compatible response shape
return {
'searchInformation': {
'totalResults': str(len(results)),
'searchTime': 0.3
},
'items': [{
'title': r['title'],
'link': r['link'],
'snippet': r['snippet'],
'displayLink': r['link'].split('/')[2] if '/' in r['link'] else ''
} for r in results]
}
# Your existing code works unchanged
response = cse_compatible_search('best python frameworks 2026')
for item in response['items']:
print(f"{item['title']} ({item['displayLink']})")
print(f"Total: {response['searchInformation']['totalResults']}")步骤 5: 验证结果并比较质量
在完全切换之前,并行运行两个 API 一周以验证结果质量。记录任何差异。
import json
from datetime import datetime
def compare_search(query: str) -> dict:
scavio_results = scavio_search(query, num=5)
scavio_urls = set(r['link'] for r in scavio_results)
comparison = {
'query': query,
'timestamp': datetime.now().isoformat(),
'scavio_count': len(scavio_results),
'scavio_top_3': [r['title'] for r in scavio_results[:3]],
}
return comparison
test_queries = [
'best python web framework 2026',
'how to deploy fastapi production',
'typescript vs python performance'
]
for q in test_queries:
result = compare_search(q)
print(f"Query: {q}")
print(f" Scavio: {result['scavio_count']} results")
print(f" Top 3: {result['scavio_top_3']}")
print()Python 示例
import os, requests
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
def search(query, num=10):
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json'},
json={'query': query, 'country_code': 'us', 'num_results': num})
resp.raise_for_status()
return resp.json().get('organic_results', [])
def cse_compat(query, **kw):
results = search(query, num=kw.get('num', 10))
return {'items': [{'title': r['title'], 'link': r['link'],
'snippet': r.get('snippet', '')} for r in results]}
resp = cse_compat('python frameworks 2026')
for item in resp['items']:
print(f"{item['title']} -> {item['link']}")
print(f'Total: {len(resp["items"])} results at $0.005')JavaScript 示例
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
async function search(query, num = 10) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': SCAVIO_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, country_code: 'us', num_results: num })
});
return (await resp.json()).organic_results || [];
}
async function cseCompat(query) {
const results = await search(query);
return { items: results.map(r => ({ title: r.title, link: r.link, snippet: r.snippet || '' })) };
}
cseCompat('python frameworks 2026').then(resp => {
resp.items.forEach(i => console.log(`${i.title} -> ${i.link}`));
console.log(`Total: ${resp.items.length} results at $0.005`);
});预期输出
best python frameworks 2026 -> https://example.com/...
Django vs FastAPI in 2026: Which Should You Choose?
-> https://blog.example.com/django-vs-fastapi-2026
Top 10 Python Web Frameworks for Production
-> https://example.com/top-python-frameworks
Total: 10 results at $0.005