LoHoSearch 用于批量测试,可行性取决于你能掌握多少接口细节。批量测试本质上就是把大量查询喂给搜索服务,再统一收集结果,过程中要处理限流、超时、结果格式不一致等问题。只要先确认好接口行为,再用脚本控制节奏,就能稳定跑完测试集。
可行,但必须先把三件事确认清楚:LoHoSearch 的接口是否允许批量化调用、是否有限流参数、以及你是否有办法区分正常结果与异常响应。建议从小批量开始,先串行后并发,并在脚本里加入重试与日志记录。没有接口文档时,不应直接高并发压测。
先确认接口边界,再谈批量
不要一上来就写循环调用。你需要先回答四个问题:
- LoHoSearch 提供的是单条查询接口,还是原生批量接口?若只有单条接口,批量的本质就是多次请求。
- 限流策略是什么?每分钟/每秒允许多少次请求?是否返回 429 或特殊响应头?
- 鉴权方式是什么?API Key 放在 header 还是 query 参数?
- 响应格式是否稳定?是否包含请求 ID、耗时、结果列表等字段,方便校验?
这些信息通常可从官方文档或接口返回的错误码中得出。没有文档时,可以先发起一个请求,观察响应头和返回体,再决定批量策略。
写一个可复用的批量调用骨架
下面给出一个 Python 脚本骨架,适用于「单条查询接口 + 串行调用」的场景。它读取一个关键词列表,逐个调用 LoHoSearch,并将状态和原始响应写入 CSV。你根据实际接口地址、鉴权字段和返回结构修改即可。
import csv
import time
import requests
import json
API_KEY = '你的API_KEY'
BASE_URL = 'https://api.lohosearch.example'
def search(query, params=None):
headers = {'Authorization': f'Bearer {API_KEY}'}
payload = {'q': query}
if params:
payload.update(params)
resp = requests.get(f'{BASE_URL}/search', headers=headers, params=payload, timeout=5)
print(f'{query} -> HTTP {resp.status_code}')
return resp
queries = ['关键词1', '关键词2', '关键词3']
with open('batch_results.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['query', 'status', 'result_count', 'raw'])
for q in queries:
try:
r = search(q)
if r.status_code == 200:
data = r.json()
count = len(data.get('results', []))
writer.writerow([q, 'OK', count, json.dumps(data, ensure_ascii=False)])
else:
writer.writerow([q, f'HTTP {r.status_code}', '', r.text[:500]])
except Exception as e:
writer.writerow([q, f'ERROR: {e}', '', ''])
time.sleep(1)
注意几点:time.sleep(1) 是保守的请求间隔;如果确认限流上限较高,可以改为 0.2 秒或不 sleep。response.text[:500] 先把错误信息截断,避免因写入过长内容导致 CSV 损坏。这里没有验证响应是否为预期 JSON 结构,你需要在解析前做校验。
用并发提高吞吐,但要有重试和退避
确认串行调用稳定后,再考虑并发。并发能明显缩短总耗时,但会提高触发限流的概率。可以先用 2-3 个线程试跑,再逐步增加。下面是一个使用 ThreadPoolExecutor 的最小示例,只保留关键部分。
from concurrent.futures import ThreadPoolExecutor
def worker(query):
for attempt in range(3):
try:
r = search(query)
if r.status_code == 200:
return query, 'OK', r.json()
elif r.status_code == 429:
time.sleep(2 * (attempt + 1))
else:
return query, f'HTTP {r.status_code}', r.text[:300]
except Exception as e:
if attempt == 2:
return query, f'ERROR: {e}', ''
time.sleep(1)
return query, 'FAIL', ''
with ThreadPoolExecutor(max_workers=3) as pool:
results = list(pool.map(worker, queries))
这里的关键点是:对 429 响应做指数退避,对异常做有限重试。如果并发数持续超过限流阀值,你会不断收到 429,这时需要降低并发或增加间隔。
结果校验与数据落盘
批量测试不只是拿到结果,还要能判断哪些结果是可用的。建议你记录以下信息:HTTP 状态码、请求耗时(如果接口返回)、结果数量、响应体整体 MD5 或长度、以及原始 JSON。这样后续做结果对比时,你能区分「接口错误」和「正常无结果」之间的差别。
CSV 适合保存摘要,但原始 JSON 建议单独保存到文件目录。可以把每个查询的原始响应单独存成一个文件,命名包含时间戳和查询序号,便于回溯。以下是一个简单逻辑:
for idx, q in enumerate(queries):
raw = ...
file_name = 'raw/' + str(idx) + '_' + q.replace('/', '_') + '.json'
with open(file_name, 'w', encoding='utf-8') as fp:
json.dump(raw, fp, ensure_ascii=False)
上面的代码只是示意,真正使用时需要和前面的请求逻辑整合。
风险边界与验收清单
批量测试可行,但风险通常出在以下几个方面:
- 限流导致 IP 被暂时封禁:建议先小规模试跑,观察响应头中的 rate limit 字段。
- 接口字段不稳定:比如响应中结果列表的 key 名称变化,脚本直接按固定 key 解析就会出错。建议用 schema 校验,但如果没有文档,需要做好容错。
- 批量测试产生大量调用,可能产生费用或消耗配额:先评估成本和账户额度。
- 不要用一次性脚本跑完就不管:结果日志要留档,便于后续对比。
最后给你一个验收清单:
- 用 5 条关键词连续串行调用,确认接口返回格式一致。
- 检查是否出现 429 或超时,记录出现频率。
- 将并发数从 1 逐步提升,找到稳定的临界值。
- 随机抽检 10% 的结果,人工核对内容是否是预期返回。
- 确认脚本在中断后可以从断点续跑,而不是全部重跑。
这样跑下来的批量测试结果,才具备判断价值。