从 Serper 切到 SERP API:200 行代码 diff 实战
背景
接手一个老项目,原来用 Serper.dev 抓 Google SERP,现在切到 SERP API。两家 API 设计相近,理论上 1-2 天能切完。实际做完,代码 diff 大约 200 行,踩了 4 个坑,记下来给同样要切的人。
API 差异
| 维度 | Serper.dev | SerpBase |
|---|---|---|
| 协议 | GET / POST 都行 | 仅 POST |
| 鉴权 header | X-API-KEY(全大写) | X-API-Key(大写 X-API + 小写 Key) |
| Endpoint | google.serper.dev/search | api.serpbase.dev/google/search |
| Body 格式 | JSON | JSON |
| 默认 num | 10 | 10 |
| 返回 organic key | organic | organic |
| 返回 PAA key | peopleAlsoAsk(camelCase) | people_also_ask(snake_case) |
| 返回 KG key | knowledgeGraph | knowledge_graph |
| 返回 AI Overview | aiOverview | ai_overview |
| Snippet 字段 | snippet | snippet |
| 错误响应 | {"message": "..."} | {"status": "error", "message": "...", "request_id": "..."} |
JSON 字段命名风格:Serper 是 camelCase,SerpBase 是 snake_case。这是最大差异,大约 60% 的代码差异都来自这里。
实际 diff 例子
Python 调用层
Serper 之前:
importrequests API_KEY="your-serper-key"ENDPOINT="https://google.serper.dev/search"defsearch(query):r=requests.post(ENDPOINT,headers={"X-API-KEY":API_KEY,"Content-Type":"application/json"},json={"q":query},)returnr.json()SerpBase 之后:
importrequests API_KEY="your-serpbase-key"ENDPOINT="https://api.serpbase.dev/google/search"defsearch(query):r=requests.post(ENDPOINT,headers={"X-API-Key":API_KEY,"Content-Type":"application/json"},json={"q":query},)returnr.json()差异:3 行(URL + header name + key 名)。注意 header 大小写不一致:X-API-KEYvsX-API-Key,这是最容易踩的第一个坑。
业务解析层
Serper 之前:
defget_organic(data):returndata.get("organic",[])defget_paa(data):returndata.get("peopleAlsoAsk",[])defget_kg(data):returndata.get("knowledgeGraph",{})SerpBase 之后:
defget_organic(data):returndata.get("organic",[])defget_paa(data):returndata.get("people_also_ask",[])defget_kg(data):returndata.get("knowledge_graph",{})差异:每行只改字段名。grep -r "peopleAlsoAsk\|knowledgeGraph\|aiOverview" .全文替换即可。
4 个踩过的坑
1. PAA 字段的嵌套结构不同。
Serper 的peopleAlsoAsk每项是{question, snippet, link, title}。SerpBase 的people_also_ask多一个source字段,有时 PAA 项里直接嵌link。
老代码假设 PAA 每项都有link,某些 SerpBase 返回里 link 在 source 里,导致KeyError。改成:
defget_paa_link(item):returnitem.get("link")oritem.get("source",{}).get("link")2. knowledgeGraph 不再是简单顶层 key。
Serper 的knowledgeGraph是平铺对象。SerpBase 的knowledge_graph嵌套更深,有些查询返回knowledge_graph.title/description,有些返回knowledge_graph.attributes。
老代码kg.get("title")在 SerpBase 上经常拿到None。改成:
defget_kg_title(kg):returnkg.get("title")orkg.get("name")3. ai_overview 触发判断的字段不同。
Serper 的aiOverview存在就是触发了。SerpBase 的ai_overview即使不存在,响应里也可能有aiOverviewCited这种 metadata 字段(在某些 query 上)。
判断触发更稳的方法:检查ai_overview.text是否非空,不要只看 key 是否存在。
4. error response 的 code 字段。
Serper 错误响应是{"message": "..."}。SerpBase 是{"status": "error", "message": "...", "request_id": "..."}。
如果你之前用r.status_code != 200判断成功,两家都 OK。如果用r.json().get("success"),Serper 是 True,SerpBase 没有这个字段,要改成r.json().get("status") == "ok"。
request_id这个字段是 SerpBase 独有的,落库时存下来,出问题查日志直接用。
切换流程(给团队 SOP)
- 在独立 branch 上做 API 层改造,业务层暂时兼容两家返回
- 跑 1 周平行测试,两家结果对账,差异 < 1% 才推进
- 切流量,留 30 天 fallback(Serper 账号别立刻注销)
- 删 fallback,清代码
性能差异
我切的项目每天 30,000 搜索,实测:
- Serper P50:~1.2s
- SerpBase P50:~1.4s
切完之后 0.2s latency 差异在业务上不可感知(下游还有 LLM 推理 2-3s)。
价格上:同样 30,000 搜索,Serper $30(50/50k),SerpBase Growth $12(50/125k),节省 60%。
一个意外发现
切完之后,我项目的 credit 不过期(SerpBase 标准包),可以一次性买 1 年的搜索量放着。Serper 同样是预付,但入门包单价高。
如果项目月用量稳定,SerpBase 长期持有更便宜。
总结
切换本身不难,1-2 天工作量。最大的隐藏成本是 JSON 字段命名风格的差异,业务层要全面 grep 替换。其它都是边角问题,跑两周对账都能 catch。
100 次免费试用:serpbase.dev 注册,不用绑卡,跑 1 周平行测试用。
