SERP API JSON Schema 演进版本管理实战

SERP API 返回 JSON 会演进,新字段加、旧字段改,下游解析会崩。做好版本管理,升级不炸。

1. 为什么需要 Schema 管理

SERP API 返回 JSON 的结构,不同版本有差异:

  • v1: organic[].title / snippet
  • v2: 加 people_also_ask[](延伸问题)
  • v3: 加 ai_overview(AI 摘要)
  • v4: organic[].snippet 改名为 organic[].description(破坏性)

下游解析器跟着版本走,不管理就会崩。

2. JSON Schema 定义

先定义 API 返回的 schema:

json 复制代码
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://serpbase.dev/schema/v1/search.json",
  "type": "object",
  "properties": {
    "status": { "type": "integer" },
    "request_id": { "type": "string" },
    "organic": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["title", "link"],
        "properties": {
          "title": { "type": "string" },
          "link": { "type": "string" },
          "snippet": { "type": "string" },
          "position": { "type": "integer" }
        }
      }
    },
    "people_also_ask": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "question": { "type": "string" },
          "answer": { "type": "string" }
        }
      }
    }
  },
  "required": ["status", "organic"]
}

3. Schema 版本管理

git 管理 + semver 版本号:

bash 复制代码
schemas/
├── v1.0.0-search.json
├── v1.1.0-search.json   # 加 people_also_ask
├── v2.0.0-search.json   # 破坏性:snippet → description
└── v3.0.0-search.json   # 加 ai_overview
  • minor(1.1.0):加字段,不破坏
  • major(2.0.0):改字段名,破坏

4. 校验库

Python 用 jsonschema:

python 复制代码
import jsonschema
from jsonschema import validate, Draft202012Validator

def validate_serp(data, schema_path='schemas/v1.1.0-search.json'):
    """校验 SERP 数据是否符合 schema"""
    schema = json.load(open(schema_path))

    try:
        validate(instance=data, schema=schema)
        return True, None
    except jsonschema.ValidationError as e:
        return False, str(e)

# 测试
data, error = validate_serp(serp_response)
if not data:
    print(f"Schema violation: {error}")

5. 自动适配不同版本

下游解析器适配多个版本:

python 复制代码
def parse_serp(data):
    """自适应解析 SERP 数据,兼容多版本"""

    # 检测版本
    version = detect_version(data)

    if version >= '2.0.0':
        # 新版:description 替代 snippet
        snippet_field = 'description'
    else:
        # 旧版:snippet
        snippet_field = 'snippet'

    results = []
    for item in data.get('organic', []):
        results.append({
            'title': item['title'],
            'snippet': item.get(snippet_field, ''),  # 兼容
            'link': item['link'],
            'position': item.get('position', 0)
        })

    # ai_overview(v3+)
    if 'ai_overview' in data:
        results.append({
            'type': 'ai_overview',
            'text': data['ai_overview'].get('text', '')
        })

    return results

def detect_version(data):
    """检测数据版本"""
    if 'ai_overview' in data:
        return '3.0.0'
    if 'people_also_ask' in data:
        return '1.1.0'
    return '1.0.0'

6. 兼容策略

3 种兼容策略:

python 复制代码
class SchemaCompat:
    """Schema 兼容处理"""

    def __init__(self):
        self.versions = {
            '1.0.0': self.parse_v1,
            '1.1.0': self.parse_v1_1,
            '2.0.0': self.parse_v2,
            '3.0.0': self.parse_v3
        }

    def parse(self, data):
        version = detect_version(data)
        return self.versions[version](data)

    def parse_v1(self, data):
        return [{'title': i['title'], 'snippet': i['snippet']} for i in data['organic']]

    def parse_v1_1(self, data):
        items = self.parse_v1(data)
        # 加 PAA
        items.extend([
            {'type': 'paa', 'q': p['question'], 'a': p['answer']}
            for p in data.get('people_also_ask', [])
        ])
        return items

    def parse_v2(self, data):
        items = []
        for i in data['organic']:
            items.append({
                'title': i['title'],
                'description': i['description'],  # 新版字段
                'link': i['link']
            })
        return items

    def parse_v3(self, data):
        items = self.parse_v2(data)
        if 'ai_overview' in data:
            items.append({'type': 'ai_overview', 'text': data['ai_overview']['text']})
        return items

7. 下游影响分析

每次 Schema 升级,评估下游影响:

python 复制代码
def analyze_schema_change(old_schema, new_schema):
    """分析 schema 变化的破坏性"""
    breaking = []
    additive = []

    # 递归对比
    def walk(old, new, path=''):
        if isinstance(old, dict) and isinstance(new, dict):
            # 删除字段 = 破坏
            for k in old:
                if k not in new:
                    breaking.append(f'{path}.{k} removed')
            # 新增字段 = additive
            for k in new:
                if k not in old:
                    additive.append(f'{path}.{k} added')
            # 递归
            for k in old:
                if k in new:
                    walk(old[k], new[k], f'{path}.{k}')
        elif isinstance(old, dict) and isinstance(new, dict):
            # 类型变化 = 破坏
            if old.get('type') != new.get('type'):
                breaking.append(f'{path} type changed')

    walk(old_schema, new_schema)
    return breaking, additive

8. 版本兼容测试

自动化测试保证兼容:

python 复制代码
import pytest

# 所有历史版本的测试数据
HISTORICAL = {
    '1.0.0': {...},  # 只有 organic
    '1.1.0': {...},  # + paa
    '2.0.0': {...},  # snippet → description
    '3.0.0': {...}   # + ai_overview
}

@pytest.mark.parametrize('version,data', HISTORICAL.items())
def test_parse_compat(version, data):
    """所有历史版本都能解析"""
    parser = SchemaCompat()
    result = parser.parse(data)
    assert result is not None
    assert isinstance(result, list)

9. 实战:30 天数据

跑 30 天 Schema 管理:

指标 数值
Schema 版本 3 次(1.1 → 2.0 → 3.0)
破坏性变更 1 次(snippet → description)
下游解析失败 0
回滚次数 0
平均迁移时间 30 分钟

10. 最佳实践

几点经验:

  1. API 侧加版本参数 :?v=3.0.0
  2. 保持 snippet 兼容:加 description 的同时保留 snippet(过渡期)
  3. schema 文档化:每个字段标注引入版本
  4. 提前通知:破坏性变更至少提前 30 天
  5. 灰度:先灰度 1% 流量验证

11. API 版本参数

serpbase 支持版本参数:

python 复制代码
r = requests.post(
    'https://api.serpbase.dev/google/search?v=3.0.0',
    headers={'X-API-Key': key},
    json={'q': query}
)

12. 总结

JSON Schema 版本管理 5 件事:

  1. 定义 schema(v1.0.0)
  2. git + semver 管理
  3. 校验(jsonschema)
  4. 兼容解析(多版本适配)
  5. 破坏性评估 + 灰度

代码 GitHub 公开,clone 跑起来。

参考文档

本文 API 示例参考 serpbase 文档,接口路径、参数和返回字段以官方文档为准。

相关推荐
VIP_CQCRE14 小时前
用 Ace Data Cloud 快速接入 Suno:把 AI 音乐生成能力集成进你的产品
人工智能·api·suno·ai音乐·acedatacloud
用户77833661321118 小时前
用搜索数据 API 做一个关键词联想组件(防抖 + 缓存 + 可复用)
python·api
爱奥尼欧19 小时前
14.输出解析器-Pydantic与JSON
人工智能·学习·langchain·json
VIP_CQCRE1 天前
Veo API 实战:用一句镜头语言,批量生成商业级 AI 视频
aigc·api·ai视频·acedatacloud·veo
VIP_CQCRE2 天前
用 Ace Data Cloud 快速接入 MiniMax H3:把 AI 视频生成能力变成可调用的生产力
ai·aigc·api·视频生成·acedatacloud
vortex52 天前
composer.json 可写场景下的利用手段
android·json·composer
Ming_studying2 天前
HTML + CSS + JavaScript实现可视化JSON工具:格式化、折叠、搜索与错误定位
javascript·css·html·json·数据可视化·web工具
CappuccinoRose2 天前
JSON 数据交互规范
json·交互
dogstarhuang2 天前
OpenAI GPT-5.6 降价后如何重算 API 账单?多模型路由与成本治理实战
服务器·网络·人工智能·大模型·api·ai应用开发·接口管理