apify-generate-output-schema

apify-generate-output-schema

热门

通过分析源码,为 Apify Actor 生成输出 Schema(dataset_schema.json、output_schema.json、key_value_store_schema.json)。适用于创建或更新 Actor 输出 Schema 的场景。

2231Star
244Fork
更新于 2026/6/25
SKILL.md
只读
名称
apify-generate-output-schema
描述

通过分析源码,为 Apify Actor 生成输出 Schema(dataset_schema.json、output_schema.json、key_value_store_schema.json)。适用于创建或更新 Actor 输出 Schema 的场景。

生成 Actor 输出 Schema

你正在为 Apify Actor 生成输出 Schema 文件。输出 Schema 用于告诉 Apify Console 如何展示运行结果。你需要分析 Actor 的源代码,创建 dataset_schema.jsonoutput_schema.json 以及 key_value_store_schema.json(若 Actor 使用了键值存储/key-value store),并更新 actor.json

核心原则

  • 代码优先,拒绝凭空臆测:先阅读 Actor 的源码,搞清楚它到底向数据集(dataset)写入了哪些数据,绝不要主观猜想
  • 所有字段均设为可空(nullable):API 和网页响应往往不可控——务必统一设置 "nullable": true
  • 示例数据必须脱敏/匿名化:示例中切勿包含真实的用户 ID、用户名或个人敏感信息
  • 与代码交叉验证:如果存在 TypeScript 类型定义,请结合类型定义和实际生成数据的代码双重校验 Schema
  • 复用现有规范:生成 Schema 前,先检查同一仓库下的其他 Actor 是否已有输出 Schema,保持结构、命名规范、描述风格和格式一致
  • 避免重复造轮子:直接复用代码库中现有的类型定义、接口和工具函数,不要重复定义

阶段 1:探明 Actor 结构

目标:定位 Actor 并理清其输出数据

初始请求:$ARGUMENTS

操作步骤

  1. 创建包含所有阶段的任务清单(todo list)
  2. 找到包含 actor.json.actor/ 目录
  3. 阅读 actor.json 以了解 Actor 的配置
  4. 检查 dataset_schema.jsonoutput_schema.jsonkey_value_store_schema.json 是否已存在
  5. 在仓库中检索已有 Schema:查找其他 .actor/ 目录或 Schema 文件(例如 **/dataset_schema.json**/output_schema.json**/key_value_store_schema.json),学习仓库内部规范——保持描述风格、字段命名、示例格式和总体结构的一致性
  6. 找出所有向数据集写入数据的位置:
    • JavaScript/TypeScript:搜索 Actor.pushData(dataset.pushData(Dataset.pushData(
    • Python:搜索 Actor.push_data(dataset.push_data(Dataset.push_data(
  7. 找出所有向键值存储写入数据的位置:
    • JavaScript/TypeScript:搜索 Actor.setValue(keyValueStore.setValue(KeyValueStore.setValue(
    • Python:搜索 Actor.set_value(key_value_store.set_value(KeyValueStore.set_value(
  8. 找到输出类型定义——直接复用,无需从零搭建:
    • TypeScript:查找输出相关的接口/类型(例如在 src/types/src/types/output.ts 中)。如果已有接口或类型定义了输出结构,直接据此推导 Schema 字段——不要新建一套并行定义
    • Python:查找 TypedDict、dataclass 或 Pydantic 模型定义。以现有的字段名、类型和文档注释(docstrings)作为单一事实来源(source of truth)
  9. 检查代码库中是否有现成的用于 Schema 生成或校验的共享工具函数/辅助函数——尽量复用,避免新建重复逻辑
  10. 如果 actor.json 中存在内联的 storages.datasetstorages.keyValueStore 配置,记录下来以便后续迁移

将排查结果呈报给用户:列出探明的所有数据集输出字段、键值存储的键(key)、对应类型以及来源位置。


阶段 2:生成 dataset_schema.json

目标:创建完整的数据集 Schema,包含字段定义与视图展示配置

文件结构

{
    "actorSpecification": 1,
    "fields": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "object",
        "properties": {
            // 此处列出所有输出字段——包含 Actor 可能产生的所有字段,
            // 绝不仅限于 overview 视图中展示的部分
        },
        "required": [],
        "additionalProperties": true
    },
    "views": {
        "overview": {
            "title": "Overview",
            "description": "Most important fields at a glance",
            "transformation": {
                "fields": [
                    // 8-12 个最重要的字段名称
                ]
            },
            "display": {
                "component": "table",
                "properties": {
                    // 每个概览字段的展示配置
                }
            }
        }
    }
}

保持与已有 Schema 的一致性

如果在阶段 1(步骤 5)中在仓库中找到了已有的输出 Schema,请遵循其规范:

  • 统一描述书写风格(首字母大写 vs 小写、末尾加句号 vs 不加句号等)
  • 统一字段命名约定(camelCase 驼峰命名 vs snake_case 蛇形命名)——这也必须与 Actor 代码实际生成的键名相匹配
  • 统一示例值风格(例如日期格式、URL 模式、占位符名称)
  • 统一视图结构(概览中包含的字段数量、展示格式的选择)
  • 统一 JSON 格式化风格(缩进格数、属性排序、空格)——同一仓库中的所有 Schema(包括独立的 Actor)必须使用完全一致的格式

当 Actor 代码中已包含定义清晰的 TypeScript 接口或 Python 类型类时,直接从这些类型推导字段,而不是重新逐行分析 pushData/push_data 调用。类型定义就是权威来源。

硬性规则(绝无例外)

规则 细则
所有字段均放入 properties fields.properties 对象必须包含 Actor 可以输出的每一个字段,不能只写概览视图中显示的字段。views 部分只是筛选子集进行展示,properties 部分必须是完整全集
"nullable": true 作用于每个字段——因为外部 API 充满不确定性
"additionalProperties": true 必须同时加在顶层 fields 对象以及 properties 内的每个嵌套对象上。这是最常被遗漏的规则——两个层级缺一不可
"required": [] 始终为空数组——必须同时加在顶层 fields 对象以及 properties 内的每个嵌套对象
示例值必须脱敏 禁止出现真实用户 ID、用户名或真实内容
"nullable" 必须配合 "type" 使用 校验器 AJV 如果看到 nullable 但同级缺少 "type" 会直接报错

警告——最常见错误

  1. 只包含在概览视图中出现的字段。fields.properties 必须列出所有输出字段,即使它们不在 views 部分中。
  2. 只在嵌套的对象类型属性上添加 "required": []"additionalProperties": true,却忘记在顶层 fields 对象上添加。两个层级都必须配备。

注意nullable 是 Apify 针对 JSON Schema draft-07 的自定义扩展属性。这是符合预期且完全正确的。

字段类型常见模式

字符串字段(String):

"title": {
    "type": "string",
    "description": "Title of the scraped item",
    "nullable": true,
    "example": "Example Item Title"
}

数值字段(Number):

"viewCount": {
    "type": "number",
    "description": "Number of views",
    "nullable": true,
    "example": 15000
}

布尔字段(Boolean):

"isVerified": {
    "type": "boolean",
    "description": "Whether the account is verified",
    "nullable": true,
    "example": true
}

数组字段(Array):

"hashtags": {
    "type": "array",
    "description": "Hashtags associated with the item",
    "items": { "type": "string" },
    "nullable": true,
    "example": ["#example", "#demo"]
}

嵌套对象字段(Object):

"authorInfo": {
    "type": "object",
    "description": "Information about the author",
    "properties": {
        "name": { "type": "string", "nullable": true },
        "url": { "type": "string", "nullable": true }
    },
    "required": [],
    "additionalProperties": true,
    "nullable": true,
    "example": { "name": "Example Author", "url": "https://example.com/author" }
}

枚举字段(Enum):

"contentType": {
    "type": "string",
    "description": "Type of content",
    "enum": ["article", "video", "image"],
    "nullable": true,
    "example": "article"
}

联合类型(Union type,例如 TypeScript 中的 ObjectType | string):

"metadata": {
    "type": ["object", "string"],
    "description": "Structured metadata object, or error string if unavailable",
    "nullable": true,
    "example": { "key": "value" }
}

脱敏示例值

使用真实合理但通用的假数据。遵循对应平台的 ID 格式约定:

字段类型 示例处理方式
ID 匹配对应平台的格式与长度(例如 YouTube 视频 ID 固定为 11 位)
用户名 "exampleuser""sampleuser123"
展示名称 "Example Channel""Sample Author"
URL 使用平台的标准 URL 格式搭配伪造 ID
日期 "2025-01-15T12:00:00.000Z"(ISO 8601 格式)
文本内容 通用描述性文本,例如 "This is an example description."

视图(Views)配置

  • transformation.fields:挑选 8–12 个最重要的字段名称(列表中的顺序即为 UI 中表格列的顺序)
  • display.properties:概览视图中的每个字段对应一个配置条目,包含 label(标签名称)和 format(展示格式)
  • 可选展示格式:"text""number""date""link""boolean""image""array""object"

挑选能够为用户提供最直观、最有价值数据概览的字段。


阶段 3:生成 key_value_store_schema.json(若适用)

目标:如果 Actor 在键值存储(key-value store)中存有数据,请定义对应的键值存储集合

跳过此阶段:如果在阶段 1 中未发现 Actor.setValue() / Actor.set_value() 调用(默认的 INPUT 键除外)。

文件结构

{
    "actorKeyValueStoreSchemaVersion": 1,
    "title": "<描述性标题——表明键值存储包含的内容>",
    "description": "<单句描述存储的数据>",
    "collections": {
        "<collectionName>": {
            "title": "<易读的标题>",
            "description": "<此集合包含的内容>",
            "keyPrefix": "<prefix->"
        }
    }
}

如何识别集合(Collections)

按键名(Key)模式归类排查出的 setValue / set_value 调用:

  1. 固定键名(例如 "RESULTS""summary")——使用 "key"(精准匹配)
  2. 带前缀的动态键名(例如 "screenshot-${id}"f"image-{name}")——使用 "keyPrefix"

每个分组归为一个集合(collection)。

集合属性说明

属性 是否必填 描述
title 在 UI 标签页中显示
description 在 UI 提示框(tooltip)中显示
key 条件必填 单文件集合的精准键名(keykeyPrefix 二选一,不可同时设置)
keyPrefix 条件必填 多文件集合的前缀(keykeyPrefix 二选一,不可同时设置)
contentTypes 限制允许的 MIME 类型(例如 ["image/jpeg"]["application/json"]
jsonSchema 用于校验 application/json 内容的 JSON Schema draft-07 规范

示例

单文件输出(例如分析报告):

{
    "actorKeyValueStoreSchemaVersion": 1,
    "title": "Analysis Results",
    "description": "Key-value store containing analysis output",
    "collections": {
        "report": {
            "title": "Report",
            "description": "Final analysis report",
            "key": "REPORT",
            "contentTypes": ["application/json"]
        }
    }
}

多文件前缀输出(例如网页截图):

{
    "actorKeyValueStoreSchemaVersion": 1,
    "title": "Scraped Files",
    "description": "Key-value store containing downloaded files and screenshots",
    "collections": {
        "screenshots": {
            "title": "Screenshots",
            "description": "Page screenshots captured during scraping",
            "keyPrefix": "screenshot-",
            "contentTyp

<!-- truncated for translation batch; full body continues in source -->