3 Response Schema
- 省略
fields只回paperId+title;paperId任何情况下都返回。 - 点号子字段只对四个字段开放:
authors.*、citations.*、references.*、embedding.specter_v2。tldr.text、externalIds.DOI这类写法官方就回 400,本地同样 400。 - 未知字段一次性回 400,不静默忽略:
{"error": "Unrecognized or unsupported fields: [bogus]"}。 - 整对象请求覆盖同名字段的子字段请求,与书写顺序无关:
fields=citations.year,citations与fields=citations,citations.year都回默认的paperId,title。 fields是列表参数:逗号分隔,同一键给两次也合并(fields=title&fields=year等价fields=title,year)。合并发生在逗号切分之前,所以fields=title,&fields=year那种悬空逗号不会粘成不存在的字段名——空字段名会被丢掉。
论文对象的字段(值可能为 null,见下):
paperId corpusId externalIds url title abstract venue publicationVenue
year publicationDate referenceCount citationCount influentialCitationCount
isOpenAccess openAccessPdf fieldsOfStudy s2FieldsOfStudy publicationTypes
journal citationStyles authors tldr embedding textAvailability
citations references
citations/references是论文数组(默认每条paperId+title,各最多 1000 条);fields=citations.title把子字段投影到每条上。authors默认每条authorId+name;authorId恒返回。url是数据集原值,不保证等于https://www.semanticscholar.org/paper/<paperId>(见 §1.5 末尾)。
「没有值」的形状不一样,别统一按 is None 判空(本快照实测):
| 字段 | 缺失形状 | 数量 |
|---|---|---|
venue | 空串 ""(恒为字符串,没有一篇是 null) | 9,018,379(45.3%) |
fieldsOfStudy | [] | 32,228 |
publicationTypes | null | 9,617,355(48.1%) |
publicationDate | null | 5,700,418 |
year | null | 15,469 |
同一篇论文的同一字段,从哪个出口取都是同一个对象:详情、batch、search / bulk /match 的行、/citations 与 /references 的邻居行、/paper/{id}/authors 与/author/{id}/papers 这八个出口共用一份投影,没有「检索侧的精简副本」。唯一例外是 matchScore——只在 match 的行上出现。
错误文案模板(状态码均 400,除注明外):
| 场景 | error |
|---|---|
| 数值参数非法 | Unacceptable query params: [offset=-1] |
| 数值参数不是数字 | Invalid value for parameter 'limit': 'abc' |
| search limit 超限 | 'limit' must be <= 100 |
| search 翻页越界 | offset + limit must be <= 1000 |
| bulk limit 超限 | 'limit' must be <= 1000 |
| bulk limit=0 | Unacceptable query params: [limit=0] |
| 列表端点 limit 超限 | 'limit' must be <= 1000 |
| 列表端点翻页越界 | offset + limit must be < 10000 |
| batch ids 为空 | Invalid request body: 'ids' must be a non-empty array |
| batch ids 超上限 | Too many ids: 501 (max 500) |
| 缺 query | Missing required parameter: query |
- 过滤值是精确匹配:
venue/fieldsOfStudy/publicationTypes写了数据集里不存在的值(含缩写、错拼)不报错,结果是 0 条。 fieldsOfStudy=Other/publicationTypes=Other指「不在这两张枚举表里的值」,不是字面写着 Other;本快照取值全部落在表内,所以这个条件一条都匹不上。两处total口径不同(§1.1):bulk回total: 0,search的total仍是过滤前的 BM25 命中数、只有data为空。- bulk 翻页只认
token,offset在这里无效(传了忽略)。 - 列表响应里
next只在还有下一页时出现(没有更多数据时整个键都没有,不是null)。
与官方接口的已知差异(「官方」列取自官方接口文档;本环境没有 API key,标未实测的几行只比到文档):
| 项 | 官方 | 本地 |
|---|---|---|
| 数据范围 | 全学科、实时更新 | 仅 CS,静态快照 |
paperId | 40 位 sha | 同;2,450 篇(0.012%)无主 sha,回退成 corpusid 字符串 |
url | 原文链接 | 数据集原值。无主 sha 的那 2,450 篇 url 尾部 sha 不是它自己的(1,458 指向别的论文、992 查不到),别拿它反推 paperId,见 §1.5 |
embedding(含 embedding.specter_v2) | SPECTER2 向量 | 字段认,值恒 null |
openAccessPdf | OA 链接 | 恒 null——isOpenAccess=true 的也一样(500 行切片里 68 篇如此),判是否开放获取只看 isOpenAccess |
citationStyles / textAvailability | 有 | 恒 null |
contexts / intents / contextsWithIntent | 有 | 恒 [] |
authors[].affiliations / homepage / externalIds | 有 | [] / null / {} |
venue | 认 ISO4 缩写 | 只认数据集里的完整名称,精确匹配;缩写形状的 journal.name 一条都筛不到(3,009 vs 0),见 §1.5 |
journal | 结构化对象 | 数据集原样透传:可能 null(4,288,986 篇)、可能没有 name 键(3,678,324 篇),键集合只会是 {name, pages, volume} 的子集,见 §1.5 |
publicationVenue | {id, name, type, issn, url, alternate_names} | 只有 {id} 或 {id, name},且 name 从 venue 借,不是官网刊物规范名,见 §1.5 |
search 的 total | 估算 | 过滤前的 BM25 命中数 |
bulk token 下标越过集合末尾 | 文档没写(未实测) | 200 + 空 data + token: null,不报错,见 §1.2 |
batch 的 ids 元素形态 | 文档只写「字符串数组」(其它形态未实测) | 字符串与 JSON 整数都按 §1.5 解析,布尔/浮点/对象/数组该槽给 null,一槽一条不去重,见 §1.9 |
/paper/{id}/authors 的 total | 文档没写是否去重(未实测) | 槽位数、重复署名各占一行,见 §1.8 |
search 的排序 | LightGBM 重排(22 维特征,其中 6 维靠语言模型;点击数据训练) | 同构的线性重排(词面覆盖、分字段词面强度、标题整串命中、venue、引用数、新近度等,权重用官方 top-10 拟合)。top-10 与官方重合 35.7%,不是复刻 |
author 统计 | 全量口径 | 本地 CS 子集口径 |
author/{id}/papers 的过滤与排序 | 文档列出 sort / year / publicationDateOrYear(未实测) | 只认 publicationDateOrYear,sort / year / venue / publicationTypes / minCitationCount 静默忽略,见 §2 |
| 速率限制 / API key | 有 | 速率限制无;访问密钥必填(见 §0) |
| 查询规模上界 | 文档没写(未实测) | 论文侧三条:括号 64 层 / 折叠后 256 分支 / 一条查询 2,000 万条 postings(search 与 bulk 共用);作者侧两条:单个姓名词 6 万项 / 500 万行、一条查询(去重后)800 万行。超限一律 400,见 §1.1、§1.2、§2 |
| 数据目录问题 | 不存在这一层(官方自己托管数据) | 本地分两类:数据层没建/半截/世代不一致 → 500,文案点名缺哪层、该跑哪个重建脚本;查询太宽 → 400,改参数能救。同一端点两种码都会出现,别把 500 当「换个写法再试」,见 §0 |
响应体量不设上限:一个请求里同时点「很多 id × 数组型字段」,本地会把整包攒完再回(citations.abstract 这类数组子字段实测每篇可达 1.3 MB,500 篇就是几百 MB 量级)。批量取详情时把fields 收窄,别在 batch 里点 citations / references。
文本形状(全量扫描,不是抽样):
| 形状 | 数量 | 出现在 | 响应里的样子 |
|---|---|---|---|
| C0 控制字符(U+0000–U+001F) | 2,556 处、分布 318 篇(另有 2 处在正文以外字段) | 标题、摘要(PDF 抽取带进来,如 re\u0007quires) | 按 JSON 规范转义成 \u00xx,json.loads 后仍是那个控制字符 |
| 裸行分隔符 U+2028 / U+2029 | 标题里 2,375 个;正文以外字段另有 38 个 | 标题 | 原样透传(UTF-8 三字节),不转义 |
孤立代理项(\udXXX) | 0 | — | 不存在,所以不会出现「编不出 UTF-8」的 500 |
第二行是唯一要小心的:U+2028/U+2029 在 JSON 字符串里合法,在 JavaScript 里却是行终止符,eval("(" + text + ")") 或 JSONP 会当场语法错误。用 JSON.parse 或标准 JSON 库就没问题。例(实测):CorpusId:157672 标题含 U+2028,CorpusId:139658 标题以 U+2029 开头。