Migrez 60K requêtes Google CSE vers une API SERP en exportant votre journal de requêtes existant, en mappant les paramètres CSE aux champs de l'API, en exécutant des tests de validation en parallèle, en basculant le trafic de production et en désactivant le projet CSE. Google CSE plafonne à 10K requêtes/jour sur les formules payantes et renvoie des structures JSON incohérentes selon les versions du schéma. Une API de recherche dédiée supprime ces limites et renvoie un JSON normalisé pour tous les types de requêtes. À $0.005/crédit avec Scavio, 60K requêtes mensuelles coûtent $300, contre $5/1K ($300) pour CSE, mais avec une sortie structurée, une prise en charge multiplateforme et aucun plafond quotidien.
Prérequis
- Python 3.8+ installé
- bibliothèque requests installée
- Une clé API Scavio depuis scavio.dev
- Accès à vos journaux de requêtes Google CSE ou analytics
Parcours
Étape 1: Exporter les requêtes CSE existantes
Extrayez votre journal de requêtes depuis les analytics CSE ou votre base de données d'application. Regroupez les requêtes par fréquence pour prioriser les tests de migration.
import os, json, csv
# Export from your app DB or CSE analytics CSV
def load_cse_queries(csv_path: str) -> list:
queries = []
with open(csv_path) as f:
reader = csv.DictReader(f)
for row in reader:
queries.append({
'query': row['query'],
'frequency': int(row.get('count', 1)),
'cse_params': {'cx': row.get('cx', ''), 'num': row.get('num', '10')},
})
queries.sort(key=lambda q: q['frequency'], reverse=True)
print(f'Loaded {len(queries)} unique queries ({sum(q["frequency"] for q in queries)} total calls)')
return queries
# Example with mock data:
queries = [{'query': 'best crm 2026', 'frequency': 500},
{'query': 'python async tutorial', 'frequency': 200}]
print(f'Top query: {queries[0]["query"]} ({queries[0]["frequency"]} calls/mo)')Étape 2: Mapper les champs CSE aux paramètres de l'API
Mappez les paramètres Google CSE comme cx, num, start et lr aux équivalents de l'API Scavio. La plupart des paramètres CSE correspondent directement ou deviennent inutiles.
import requests
API_KEY = os.environ['SCAVIO_API_KEY']
def map_cse_to_scavio(cse_query: dict) -> dict:
"""Map CSE parameters to Scavio API format."""
return {
'platform': 'google',
'query': cse_query['query'],
# CSE 'num' -> results come full by default
# CSE 'cx' -> not needed, full Google index
# CSE 'lr' -> use country/language params if needed
}
def test_single(query: dict) -> dict:
payload = map_cse_to_scavio(query)
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json=payload, timeout=15)
resp.raise_for_status()
results = resp.json().get('organic_results', [])
return {'query': query['query'], 'results': len(results), 'status': 'ok'}
print(test_single({'query': 'best crm 2026'}))Étape 3: Exécuter des tests de validation en parallèle
Testez les 100 premières requêtes en parallèle pour valider la qualité des résultats et mesurer la latence avant de basculer en production.
from concurrent.futures import ThreadPoolExecutor
import time
def validate_batch(queries: list, max_workers: int = 5) -> dict:
start = time.monotonic()
results = []
with ThreadPoolExecutor(max_workers=max_workers) as pool:
results = list(pool.map(test_single, queries[:100]))
elapsed = time.monotonic() - start
passed = sum(1 for r in results if r['results'] > 0)
failed = [r for r in results if r['results'] == 0]
print(f'Validated {len(results)} queries in {elapsed:.1f}s')
print(f'Passed: {passed}, Empty: {len(failed)}')
if failed:
print(f'Empty queries: {[f["query"] for f in failed[:5]]}')
return {'passed': passed, 'failed': len(failed), 'elapsed': round(elapsed, 1)}
validate_batch([{'query': 'best crm 2026'}, {'query': 'python async'}])Étape 4: Basculer le trafic de production
Remplacez l'appel HTTP CSE dans votre code de production par le point d'accès Scavio. Utilisez un feature flag pour un déploiement progressif.
# Production switch with feature flag
def search(query: str, use_scavio: bool = True) -> list:
if use_scavio:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': query}, timeout=10)
return resp.json().get('organic_results', [])
else:
# Legacy CSE call (keep as fallback during migration)
resp = requests.get('https://www.googleapis.com/customsearch/v1',
params={'key': os.environ.get('CSE_KEY', ''), 'cx': os.environ.get('CSE_CX', ''), 'q': query})
return resp.json().get('items', [])
results = search('best crm 2026', use_scavio=True)
print(f'{len(results)} results from Scavio')Étape 5: Désactiver le projet CSE
Après 7 jours de trafic stable sur Scavio, désactivez la facturation CSE, supprimez les identifiants CSE et archivez le journal de migration.
# Post-migration checklist:
# 1. Verify 7 days of zero CSE calls in your logs
# 2. Disable CSE API key in Google Cloud Console
# 3. Remove CSE environment variables
# 4. Archive migration validation results
def migration_report(validation: dict, daily_queries: int = 2000) -> str:
monthly = daily_queries * 30
cse_cost = monthly * 0.005 # $5/1K queries
scavio_cost = monthly * 0.005 # $0.005/credit
report = f'Migration complete: {monthly} queries/month\n'
report += f'CSE cost was: ${cse_cost:.0f}/mo\n'
report += f'Scavio cost: ${scavio_cost:.0f}/mo\n'
report += f'Validation: {validation["passed"]} passed, {validation["failed"]} empty\n'
report += 'CSE project can be decommissioned.'
return report
print(migration_report({'passed': 98, 'failed': 2}))Exemple Python
import requests, os
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def search(query):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': query}).json()
return data.get('organic_results', [])
# Replaces: requests.get('googleapis.com/customsearch/v1', params={...})
results = search('best crm 2026')
print(f'{len(results)} results')Exemple JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function search(query) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H, body: JSON.stringify({platform: 'google', query})
});
return (await r.json()).organic_results || [];
}
// Replaces: fetch(`googleapis.com/customsearch/v1?key=...&cx=...&q=${query}`)
search('best crm 2026').then(r => console.log(r.length + ' results'));Sortie attendue
A fully migrated search pipeline serving 60K+ monthly queries through Scavio instead of Google CSE, with validated result quality and a decommission checklist.