跳到正文
prodid

开放数据

下载索引

索引是可替换的。凡是它知道、而读者可以知道的一切,都以完整导出即转储的形式发布,任何人都可以下载并加载到自己的索引中。

最新转储

构建本页时,最新的转储是拍摄于 的快照。每晚 04:30 UTC 会写入一个新的转储, latest.json始终指向最新的那一个。

  • sources.ndjson.gz

    2 行 · 446 B

    每个来源一行。

    sha256 0bb6045c5ba3c73d6756f3b5ec2e8910b28f147fd80f6403d542554f8879ba8c

  • entities.ndjson.gz

    24 行 · 1.9 KiB

    每个实体(含已合并的)一行。

    sha256 1333fd9c883d4c4679a2288d874586caae364238233b04163aae8479bf72915c

  • records.ndjson.gz

    9 行 · 1.2 KiB

    每个记录(含已撤回的)一行。

    sha256 cfdfb40fd5cdd941d65adbe559ca491261971ca328316741630d155e179a4600

  • groupings.ndjson.gz

    15 行 · 501 B

    每个分组一行。

    sha256 5c562f31473d5f2b8f8551caca0f1cbb2d2f3e35f542af1e2ee6e5f35f3f261e

  • merges.ndjson.gz

    0 行 · 20 B

    每个合并(含已撤销的)一行。

    sha256 59869db34853933b239f1e2219cf7d431da006aa919635478511fabbfc8849d2

这个转储的目录是 https://dumps.prodid.org/v1/2026-10-29/,其清单是 manifest.json,写入于 2026-10-29 04:30 UTC。其许可为 index: CC0-1.0 和 claims: source。

转储存放在哪里

一个转储是一个以其快照的 UTC 日期命名的目录,放在它所用版本的目录下。v1/ 存放 v1 转储,其清单以及来源行和实体行都是 v1 文档。其中包含五个数据文件和一个清单。

dumps.prodid.org
https://dumps.prodid.org/v1/<YYYY-MM-DD>/manifest.json
https://dumps.prodid.org/v1/<YYYY-MM-DD>/sources.ndjson.gz
https://dumps.prodid.org/v1/<YYYY-MM-DD>/entities.ndjson.gz
https://dumps.prodid.org/v1/<YYYY-MM-DD>/records.ndjson.gz
https://dumps.prodid.org/v1/<YYYY-MM-DD>/groupings.ndjson.gz
https://dumps.prodid.org/v1/<YYYY-MM-DD>/merges.ndjson.gz
https://dumps.prodid.org/v1/latest.json

latest.json 最后写入。 它是最新转储的 manifest.json 的副本,在该转储的每个文件和清单都就位之后才写入。从它开始读取的人,永远不会遇到清单列出了一个尚不存在的文件,并且能根据清单自身的 snapshot_at 找到目录。

保留。 每日转储保留 7 天。每个 UTC 月份的第一个转储永久保留。被保留的转储永不改写:它的目录、文件和清单逐字节保持原样。

v0 转储。 v1 之前写入的 v0 转储仍保存在 https://dumps.prodid.org/v0/ 下,保留规则相同,v0/latest.json 继续指向其中最后一个。它们会一直符合 v0 schema。

清单。 它对五个文件各列一次,给出文件以压缩形式提供时的 SHA-256 和大小,以及解压后的行数。加载前请用摘要校验每个文件。schema 是 https://prodid.org/schemas/v1/org.prodid.dump.json,测试向量在 /spec/fixtures/v1/dump。

每个文件包含什么

每个文件都是用 gzip 压缩的 NDJSON,每行一个 JSON 对象。五个文件都读取自同一个一致的快照,因此彼此吻合:任何一行提到的每个来源都在 sources.ndjson.gz 中有自己的行,任何一行提到的每个 opid 都在 entities.ndjson.gz 中有自己的行。

文件每行对应行内容
sources.ndjson.gz来源来源的状态,与 /source/{name} 的返回完全相同。
entities.ndjson.gz实体(含已合并的)实体文档,与 /id/{opid}?history=1 的返回完全相同,包含已撤回的声明。
records.ndjson.gz记录(含已撤回的)source, key, feed, opid, body, first_seen, last_seen, withdrawn_at.
groupings.ndjson.gz分组source, kind, key, opid.
merges.ndjson.gz合并(含已撤销的)from, into, decided_at, reverted_at.

已合并的实体

已合并的 opid 在解析器上返回 308,所以它没有可复制的自身文档。它的那一行,是假如没被合并时它会返回的文档(它自己的标识符和声明仍留在它身上,这正是合并可以撤销的原因),外加一个成员 merged_into,即保留实体的 opid。合并不会形成链条:保留的实体本身从不会被合并。

记录行

索引所保存的一条记录。所有时间均为 UTC,ISO 8601。

字段含义
source来源的名称。
key记录在该来源中的 key。
feed读取它的 feed 的 URL。由数据集导入写入的记录没有此字段。
opid它解析到的单品。
body发布者发送的 org.prodid.item,原样保存。
first_seen索引首次读取它的时间。
last_seen索引最后一次读取它的时间。
withdrawn_at仅在记录被撤回时出现。

分组行

某个来源的分组解析到了哪个实体。kind 是 family 或 variant,key 是该来源的记录据以分组的内容,以明文写出而不是摘要,以便其他实现能把自己的分组与之对应。

  • family

    { "group": "<group>" }

    用于发布者分组;没有分组的记录本身构成一个系列,写作 { "key": "<key>" }。

  • variant

    { "family": <系列的 key>, "variant": { <维度>: <值>, … } }

    记录的变体,没有时为 {}。

合并行

一次合并决定:from 是被合并的 opid,into 是保留的实体,decided_at 是作出决定的时间,reverted_at 仅在合并被撤销时出现。

转储中永远不会包含的内容

转储所说的不会多于解析器已经说出的内容,外加构建这些回答所依据的记录、分组和合并。

  • 发布者的联系地址,索引保存它只是为了发送 lapse 通知。
  • 抓取日志、抓取程序的错误文本,或来源状态中没有显示的任何其他抓取信息。
  • 为什么进行某次合并,或由谁决定。
  • 为什么某个媒体哈希被屏蔽。
  • 媒体的字节。媒体声明的 media_url 指向文件,被屏蔽的哈希不会被提供。
  • 索引内部的行标识符。每一行都用名称指代来源,用 opid 指代实体。
  • 权威授权及其证据。如果某来源在 snapshot_at 时是 authoritative,它的那一行会这样写,但从转储加载的索引在其运营者作出授权之前不持有任何授权。

许可

两条规则,清单中的 licenses 两者都写明了。

  • index: CC0-1.0

    索引生成的一切

    opid、标识符映射、系列与变体层级、分组和合并。

  • claims: source

    每条声明和每条记录

    采用其来源自己声明的许可:即该来源在 sources.ndjson.gz 中那一行的 license。没有声明许可的来源什么也没有授予,prodid 也不会代表它授予任何东西。

没有发布自己发现文档的开放数据集,会以名为 dataset:<slug> 的来源进入索引,由索引的运营者从该数据集的公开导出中导入。这样的来源始终是 unverified,其 license 就是数据集自己的许可。规则见规范。

加载到你自己的索引

prodid-batch load-dump 会在一个事务中,把 v0 或 v1 转储加载到一个已迁移到相同版本的空 PostgreSQL 18 数据库。它接受转储的日期目录、manifest.json 或 latest.json,可以是本地的,也可以通过 HTTPS。

在仓库的克隆中
git clone https://github.com/productdevbook/prodid.git && cd prodid
bun install --frozen-lockfile

export DATABASE_URL=postgres://<user>:<password>@<host>:<port>/<database>
bun run --filter '@prodid/db' migrate

PRODID_OPERATOR=<your name> bun apps/batch/src/cli.ts load-dump https://dumps.prodid.org/v1/latest.json

在写入任何内容之前,每个文件都会按清单中的 sha256、bytes 和 lines 进行校验,远程转储会先下载到临时目录。非空数据库会被拒绝。PRODID_OPERATOR 会被记录为所加载合并的决定者。

若只想读取文件而不加载,先按摘要校验,再解压。下面的摘要,是构建本页时最新清单中的摘要。

sources.ndjson.gz
curl -sO https://dumps.prodid.org/v1/2026-10-29/sources.ndjson.gz
sha256sum sources.ndjson.gz
0bb6045c5ba3c73d6756f3b5ec2e8910b28f147fd80f6403d542554f8879ba8c  sources.ndjson.gz

gunzip -c sources.ndjson.gz | head -n 1

完整规则见规范中的 Dumps 一节。

规范只以英文发布,以英文文本为准。

prodid 是开源项目。帮助它成长。

给仓库加星,让更多人发现它;告诉我们哪里有问题;提交修复;或者无需 GitHub 账号,直接在这里给我们留言。