批量隔夜排名检查可让您跟踪数千个关键字,而无需消耗日间 API 配额或减慢生产系统的速度。该模式很简单:从 CSV 加载关键字,短暂延迟地循环遍历它们,将位置存储在结果文件中,并使用 cron 安排脚本。使用 Scavio API,每信用额 0.005 美元,4,000 个关键字的夜间运行成本为 20 美元,而 SerpAPI 的费用为 60 美元以上,Semrush Business 的费用为 499.95 美元以上。本教程在 Python 中构建了一个完整的夜间批处理管道。
前置条件
- 已安装 Python 3.9+
- requests 和 csv 模块(除了 requests 之外都在 stdlib 中)
- 来自 scavio.dev 的 Scavio API 密钥
- 包含要跟踪的关键字的 CSV 文件
操作指南
步骤 1: 准备您的关键字 CSV
创建一个包含关键字和 target_url 列的 CSV。该脚本将检查每个关键字并记录目标 URL 的排名。
import csv
keywords = [
{'keyword': 'best crm for startups', 'target_url': 'yoursite.com'},
{'keyword': 'crm pricing comparison 2026', 'target_url': 'yoursite.com'},
{'keyword': 'hubspot alternative small business', 'target_url': 'yoursite.com'},
]
with open('keywords.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['keyword', 'target_url'])
writer.writeheader()
writer.writerows(keywords)
print(f'Wrote {len(keywords)} keywords')步骤 2: 构建排名检查功能
对于每个关键字,调用搜索 API 并扫描目标域的自然结果。返回位置,如果在顶部结果中找不到,则返回“无”。
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
def check_rank(keyword: str, target_domain: str) -> dict:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': keyword, 'country_code': 'us'})
resp.raise_for_status()
for r in resp.json().get('organic_results', []):
if target_domain in r.get('link', ''):
return {'keyword': keyword, 'position': r['position'], 'url': r['link']}
return {'keyword': keyword, 'position': None, 'url': None}步骤 3: 批量遍历所有关键字并限制速率
读取 CSV,延迟 0.5 秒检查每个关键字以保持在速率限制范围内,并收集结果。对于 4,000 个关键字,这大约需要 35 分钟。
import time
def batch_rank_check(csv_path: str) -> list:
results = []
with open(csv_path) as f:
reader = csv.DictReader(f)
rows = list(reader)
print(f'Checking {len(rows)} keywords...')
for i, row in enumerate(rows):
result = check_rank(row['keyword'], row['target_url'])
results.append(result)
if (i + 1) % 100 == 0:
print(f' Checked {i + 1}/{len(rows)}')
time.sleep(0.5)
return results步骤 4: 保存带有时间戳的结果
将结果写入带日期的 CSV,以便您可以跟踪一段时间内的排名变化。每晚运行都会生成一个文件。
from datetime import date
def save_results(results: list) -> str:
filename = f'ranks_{date.today().isoformat()}.csv'
with open(filename, 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['keyword', 'position', 'url'])
writer.writeheader()
writer.writerows(results)
ranked = [r for r in results if r['position'] is not None]
print(f'Saved {len(results)} results to {filename}')
print(f' Ranking: {len(ranked)}, Not found: {len(results) - len(ranked)}')
return filename步骤 5: 使用 cron 安排夜间运行
添加一个 cron 条目以在每天凌晨 2 点运行脚本。该脚本在早上之前就完成了,因此当您开始工作时结果就已经准备好了。
# Add to crontab (crontab -e):
# 0 2 * * * cd /path/to/project && SCAVIO_API_KEY=your_key python batch_ranks.py
# Full script entry point:
if __name__ == '__main__':
results = batch_rank_check('keywords.csv')
save_results(results)
cost = len(results) * 0.005
print(f'Total cost: ${cost:.2f}')Python 示例
import os, csv, time, requests
from datetime import date
API_KEY = os.environ['SCAVIO_API_KEY']
ENDPOINT = 'https://api.scavio.dev/api/v1/search'
def check_rank(keyword: str, target: str) -> dict:
resp = requests.post(ENDPOINT,
headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
json={'query': keyword, 'country_code': 'us'})
resp.raise_for_status()
for r in resp.json().get('organic_results', []):
if target in r.get('link', ''):
return {'keyword': keyword, 'position': r['position'], 'url': r['link']}
return {'keyword': keyword, 'position': None, 'url': None}
def main():
with open('keywords.csv') as f:
rows = list(csv.DictReader(f))
results = []
for i, row in enumerate(rows):
results.append(check_rank(row['keyword'], row['target_url']))
if (i + 1) % 100 == 0:
print(f'Checked {i + 1}/{len(rows)}')
time.sleep(0.5)
filename = f'ranks_{date.today()}.csv'
with open(filename, 'w', newline='') as f:
w = csv.DictWriter(f, fieldnames=['keyword', 'position', 'url'])
w.writeheader()
w.writerows(results)
ranked = sum(1 for r in results if r['position'])
print(f'{ranked}/{len(results)} ranking, cost: ${len(results) * 0.005:.2f}')
if __name__ == '__main__':
main()JavaScript 示例
const fs = require('fs');
const API_KEY = process.env.SCAVIO_API_KEY;
async function checkRank(keyword, target) {
const resp = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST',
headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
body: JSON.stringify({ query: keyword, country_code: 'us' })
});
const data = await resp.json();
const match = (data.organic_results || []).find(r => r.link?.includes(target));
return { keyword, position: match?.position || null, url: match?.link || null };
}
async function main() {
const lines = fs.readFileSync('keywords.csv', 'utf8').trim().split('\n').slice(1);
const results = [];
for (const line of lines) {
const [keyword, target] = line.split(',');
results.push(await checkRank(keyword, target));
await new Promise(r => setTimeout(r, 500));
}
const ranked = results.filter(r => r.position).length;
console.log(`${ranked}/${results.length} ranking, cost: $${(results.length * 0.005).toFixed(2)}`);
}
main().catch(console.error);预期输出
Checking 4000 keywords...
Checked 100/4000
Checked 200/4000
...
Checked 4000/4000
Saved 4000 results to ranks_2026-05-13.csv
Ranking: 2847, Not found: 1153
Total cost: $20.00