社会主义经典著作集 · 接口文档

面向第三方开发者的公开说明:这个节点有什么数据,以及怎么取。

站点主页:<https://rmws1976.xyz> 数据规模:18,596 篇 · 14 位作者 · 正文合计约 6,630 万字 · 年份跨度 1820–2026


一、这个节点提供了什么

一句话:社会主义经典作家与各国社会主义领袖的著作全集, 以中文为主,按作者与年份两条线索组织,正文全文开放检索。

收录了谁

类别作者(篇数)
马克思主义经典作家马克思 2,551 · 恩格斯 1,964 · 马克思、恩格斯合著 1,719
苏联列宁 2,703 · 斯大林 2,093
中国毛泽东 1,092 · 周群 548 · 鲁迅 308
朝鲜金日成 1,433 · 金正恩 103 · 金正日 45
越南胡志明 3,598
古巴菲德尔·卡斯特罗 415
柬埔寨波尔布特 24

正文最多的几位:斯大林 1,776 万字 · 金日成 1,254 万字 · 列宁 1,190 万字 · 马克思 546 万字 · 恩格斯 526 万字。

四种进入方式

① 网页浏览 —— 按作者

https://rmws1976.xyz/           主页
https://rmws1976.xyz/a/         作者索引(14 位,带篇数 / 字数 / 年份跨度)
https://rmws1976.xyz/a/列宁.html  某位作者的全部作品(按年份分组,每条链到文章页)
https://rmws1976.xyz/p/1362.html   单篇文章(纯静态 HTML,无 JS)

② 网页浏览 —— 按年份

https://rmws1976.xyz/y/          年份索引(1820–2026,按年代分组)
https://rmws1976.xyz/y/1917.html  那一年的全部篇目(1917 年有 773 篇)

③ 爬取(不用 API 也能拿全站)

页面是预先渲染好的静态 HTML,不依赖 JS,直接 GET 即可:

爬取请自重:这台机器只有 2 核,全站约 18,800 个静态文件。建议低并发(1–2)、 加 User-Agent、两次请求之间留点间隔。要批量取正文,用 /article/{id} 更省流量。

④ 接口 —— 见下一节。检索类需求(找某个主题的论述、查某个词出现在哪篇) 走接口比爬页面高效得多。

★ 用之前必须知道:数据的已知问题

这套语料是整理+翻译来的,不是官方版本,有明确的局限:

1. 相当一部分是机器翻译的

→ 译名与术语可能与通行译本不同,引用前请对照权威版本。

2. 年份经常不准确

日期精度篇数占比
精确到日14,64278.7%
只精确到月3,23417.4%
只有年份6713.6%
没有日期490.3%

已知的具体异常(抽查所得,不是全部):

→ 不要把这里的年份当成权威,尤其做统计分析时。以年份检索(/y/、date_from) 得到的结果,请当作"大致在这段时间"来看。

3. 标题里的年份可能与实际日期不符

抽查发现 61 处标题中的年份与 date_from 字段不一致。

4. 排序陷阱

/author/{name} 与不带 q 的 /search 都是按日期升序返回的 —— 默认 limit=50 时你只会看到该作者最早的 50 篇,看起来像"他只有早期作品", 其实不是。要看他后期的著作必须翻页(offset)或调大 limit。


二、接口一览

一共 4 个接口,全部为 GET:

接口作用特点
/search语义检索 —— 找"意思相近"的文章向量相似度 + 词法加权;结果按相关性排序
/text全文检索 —— 找"哪篇文章写了这个词"字面匹配;返回每篇的出现次数和上下文片段
/article/{id}取一篇文章的全文轻量,不排队
/author/{name}取某作者的文章目录轻量,不排队;支持按日期筛

文章 id 在全站统一:/search、/text、/author 返回的 id,与网页地址 /p/{id}.html 一一对应。

语义检索还是全文检索

这两个接口互补,不是替代:

同一条问法在一个接口下没有结果、在另一个接口下命中很多,是常态。


三、通用约定

请求

返回里的判断字段

每个接口都会返回 verdict,用来判断查到了没有:

值含义
hit有命中
weak命中但相关度偏弱
absent没有命中
⚠️ 「没有命中」是 HTTP 200 + verdict: "absent",不是 404。 请用 verdict 判断,不要用 HTTP 状态码。

limit

默认值:/search 为 200,/text 与 /author 为 50。上限 1000。

/search 支持 limit=0:不返回内容,只返回准确的 total,适合先探数量。

排队与 503

/search 与 /text 是 CPU 密集操作,服务端做了并发限制。请求过多时会排队,排队超过 30 秒返回:

HTTP 503
{"verdict": "error", "busy": true,
 "message": "服务繁忙:排队超过 30 秒仍未轮到,请稍后重试"}
⚠️ 请把 503 当作「服务繁忙」重试,不要当作「没有内容」。 判断依据是 busy: true。

/article 与 /author 不排队。

响应头

头说明
X-Queue-Wait-Ms本次请求排队等待的毫秒数
X-Inflight返回时正在处理的请求数

四、GET /search —— 语义检索

参数

参数类型默认说明
qstring''检索词。可以为空 —— 空 q 时退化为"按作者/范围列出文章",按日期升序
authorstring''按作者精确过滤
authorsstring''多作者,逗号分隔,如 马克思,恩格斯。author 优先级更高
scopestring''只认 classics(经典作家范围)。见下
date_fromstring''起始日期,YYYY-MM-DD
date_tostring''结束日期,YYYY-MM-DD
offsetint0翻页偏移,见「翻页」
limitint200返回条数(上限 1000);limit=0 只返回 total

scope 说明

scope 只在没有传 author/authors 时才可能生效,且只认 classics。

传了其它值不会报错,但会在返回里给出 scope_ignored 字段说明它被忽略了 —— 请检查该字段。

周群

周群的文章无法确定具体年份,查询该作者时服务端会忽略日期过滤,并在返回里给出 date_ignored / date_note。

返回

{
  "query": "鸦片战争",
  "author": "马克思",
  "authors": ["马克思"],
  "scope": "author",
  "verdict": "hit",
  "total": 12,
  "count": 2,
  "offset": 0,
  "next_offset": 2,
  "top_sim": 0.6584,
  "weak_floor": 0.52,
  "lex_hits": 3,
  "sub_hits": 0,
  "results": [
    {
      "id": 9259,
      "title": "中国革命和欧洲革命",
      "author": "马克思",
      "date": "1853-05-20",
      "url": "/p/9259.html",
      "summary": "马克思运用对立统一规律,剖析鸦片战争后中国革命对英国经济及欧洲政治的连锁影响……",
      "tags": "马克思,对立统一规律,鸦片战争,中国革命,英国经济,欧洲政治……",
      "sim": 0.5847,
      "match": "tag"
    }
  ]
}
字段说明
total命中的文章总数(不受 limit 影响)
count本次返回的条数
offset / next_offset翻页用,见下
verdicthit / weak / absent
top_sim最高相似度;空 q 的列表模式下为 null
weak_floor弱相关判定下限,固定 0.52
lex_hits / sub_hits词法/子串加权命中的文章数
results[].sim该篇的相似度(0~1)
results[].match命中方式:tag / tag_sub / vector。空 q 的列表模式下为布尔 false
results[].tags关键词标签,逗号分隔,可当作极简摘要使用
scope_ignored仅当传入的 scope 被忽略时出现
date_ignored / date_note仅周群等日期不可靠的作者出现

翻页

用 offset + next_offset:

第 1 次:/search?q=中国&author=马克思&limit=5&offset=0
         → results 5 条,next_offset = 5
第 2 次:/search?q=中国&author=马克思&limit=5&offset=5
         → results 5 条,next_offset = 10
第 3 次:/search?q=中国&author=马克思&limit=5&offset=10
         → results 5 条,next_offset = null   ← 没有下一页了

next_offset 为 null 表示已取完,不要继续翻。

另有遗留参数 before_id(配 next_cursor),按文章 id 阈值翻页。 因为结果按相关性排序而非按 id 排序,该方式会漏结果,请勿使用。

示例

# 基本检索
curl 'https://rmws1976.xyz/search?q=%E9%B8%A6%E7%89%87%E6%88%98%E4%BA%89&author=%E9%A9%AC%E5%85%8B%E6%80%9D&limit=3'

# 只取数量
curl 'https://rmws1976.xyz/search?q=%E4%B8%AD%E5%9B%BD&author=%E9%A9%AC%E5%85%8B%E6%80%9D&limit=0'

# 按日期范围
curl 'https://rmws1976.xyz/search?q=%E4%B8%AD%E5%9B%BD&author=%E9%A9%AC%E5%85%8B%E6%80%9D&date_from=1850-01-01&date_to=1860-12-31'

五、GET /text —— 全文检索

在正文中查找字面出现的词,返回每篇的出现次数与上下文片段。

参数

参数类型默认说明
qstring—必填。为空时返回 verdict: absent 与 detail: "q 必填"
authorstring''按作者过滤。建议尽量带上,见下
limitint50返回篇数(上限 1000)

性能

带 author 时只扫描该作者的正文,不带则扫描全部 6,634 万字,耗时约为 8 倍:

场景scanned_charstook_ms
单作者约 546 万约 5~8 ms
全库66,348,218约 45~80 ms

不带 author 时,返回中会给出 suggest_author: true 与 note 提示。

返回

{
  "query": "亚罗号",
  "author": "马克思",
  "mode": "text",
  "verdict": "hit",
  "total": 4,
  "count": 2,
  "hits_total": 14,
  "scanned_chars": 5462879,
  "took_ms": 5.5,
  "results": [
    {
      "id": 6971,
      "title": "议会关于对华军事行动的辩论",
      "author": "马克思",
      "date": "1857-02-27",
      "url": "/p/6971.html",
      "hits": 8,
      "match": "text",
      "snippet": "……[注:克兰沃斯。——编者注]说过:“如果英国在‘亚罗号’事件上没有充分的根据,那末英国的一切行动自始至终都是错误的。”……",
      "tags": "马克思,帕麦斯顿政府,侵华战争……"
    }
  ]
}
字段说明
total命中的文章数
hits_total命中的总次数(同一篇多次出现累计)
results[].hits该篇内的出现次数
results[].snippet命中处的上下文片段,不是全文;要全文请用 /article/{id}
scanned_chars / took_ms本次扫描字数与服务端耗时
note / suggest_author仅在不带 author 时出现

六、GET /article/{id} —— 文章全文

参数说明
id文章 id(路径参数)
{
  "id": 7038,
  "title": "鸦片贸易史",
  "author": "马克思",
  "date": "1858-09-03",
  "url": "/p/7038.html",
  "tags": "英国政府,印度鸦片,中国,垄断,走私,财政利益……",
  "content": "卡·马克思\n\n正因为英国政府把在印度种植鸦片的垄断权据为己有,中国才采取了禁止鸦片贸易的措施。……"
}

id 不存在时返回 HTTP 404:

{"detail": "not found: 99999999"}
content 是整篇正文,长文可达两万余字,批量获取时注意体积。

七、GET /author/{name} —— 作者文章目录

参数类型默认说明
namestring—作者名(路径参数,需 URL 编码)
limitint50返回条数
offsetint0偏移,翻页用
date_from / date_tostring''日期范围
⚠️ 返回顺序是「按日期升序」,也就是从最早开始。 默认 limit=50 时你只会拿到 这位作者最早的 50 篇——看起来就像"他只有早期作品",其实不是。 例:/author/金日成?limit=50 返回的是 1930–1945 年的文章,而 total 是 1433, 最后一页(offset=1430)是 2007 年的。 要看他后期的著作,必须翻页或把 limit 调大。 (/search 在不带 q 的列表模式下也是按日期升序,同理。)
{
  "author": "马克思",
  "verdict": "hit",
  "total": 2551,
  "limit": 2,
  "offset": 0,
  "articles": [
    {"id": 1,    "title": "青年在选择职业时的考虑", "date": "1835-08",    "url": "/p/1.html"},
    {"id": 7327, "title": "根据《约翰福音》第15章……", "date": "1835-08-10", "url": "/p/7327.html"}
  ]
}
⚠️ 本接口返回的字段名是 articles(不是 results),每项只有 id / title / date / url 四个字段 —— 没有摘要与标签,需要详情请另调 /article/{id}。

作者不存在时返回 verdict: "absent" 与空的 articles(HTTP 仍为 200)。

已知作者(14 位):马克思、恩格斯、马克思/恩格斯合著、列宁、斯大林、毛泽东、胡志明、金日成、金正日、金正恩、菲德尔·卡斯特罗、周群、鲁迅、波尔布特。


八、错误与边界速查

情况HTTP返回
正常命中200verdict: "hit" 或 "weak"
没有命中200verdict: "absent", total: 0
/text 缺少 q200verdict: "absent", detail: "q 必填"
排队超过 30 秒503{"busy": true, "message": "服务繁忙:…"}
/article/{id} 不存在404{"detail": "not found: …"}
/author/{name} 不存在200verdict: "absent", articles: []
传入不支持的 scope200正常返回,另含 scope_ignored

两点最容易错:

  1. 「没有命中」是 200 而不是 404 —— 用 verdict 判断。
  2. 503 是「繁忙」而不是「没有」 —— 用 busy 判断,然后重试。

九、调用示例

Python

import json, urllib.error, urllib.parse, urllib.request

BASE = "https://rmws1976.xyz"

def kb(path, **params):
    url = BASE + path + ("?" + urllib.parse.urlencode(params) if params else "")
    try:
        with urllib.request.urlopen(url, timeout=60) as r:
            return json.loads(r.read().decode("utf-8"))
    except urllib.error.HTTPError as e:
        d = json.loads(e.read().decode("utf-8", "replace"))
        d["_http"] = e.code
        return d

# 语义检索
d = kb("/search", q="鸦片战争", author="马克思", limit=3)
if d.get("busy"):
    print("服务繁忙,稍后重试")
elif d["verdict"] == "absent":
    print("没有相关内容")
else:
    print("共 %d 篇" % d["total"])
    for it in d["results"]:
        print(" ", it["id"], it["title"], "相似度 %.3f" % it["sim"])

# 全文检索(带词频)
t = kb("/text", q="亚罗号", author="马克思", limit=5)
for it in t["results"]:
    print(" ", it["title"], "出现", it["hits"], "次")

# 翻页(用 offset / next_offset)
seen, offset = [], 0
while True:
    d = kb("/search", q="中国", author="马克思", limit=50, offset=offset)
    if d.get("busy"):
        continue
    seen += [it["id"] for it in d["results"]]
    offset = d.get("next_offset")
    if offset is None:
        break
print("共取到", len(seen), "篇")

# 作者目录 → 读全文
a = kb("/author/" + urllib.parse.quote("马克思"), limit=3)
full = kb("/article/%d" % a["articles"][0]["id"])
print(full["title"], "正文", len(full["content"]), "字")

Lua

-- 需要支持 HTTPS 的 HTTP 库(如 luasocket + luasec),以及一个 JSON 库
local http  = require("socket.http")
local ltn12 = require("ltn12")
local json  = require("cjson")

local function kb(path)
  local body = {}
  http.request{
    url  = "https://rmws1976.xyz" .. path,
    sink = ltn12.sink.table(body),
  }
  return json.decode(table.concat(body))
end

local d = kb("/search?q=" .. urlencode("鸦片战争") .. "&limit=5")
if d.busy then
  print("服务繁忙,稍后重试")
elseif d.verdict == "absent" then
  print("没有相关内容")
else
  print("共 " .. d.total .. " 篇")
  for i, it in ipairs(d.results) do
    print(i .. ". " .. it.title .. "  " .. it.date)
  end
end
URL 里的中文需先做百分号编码。Lua 标准库没有这个函数,请用运行环境提供的方法。

curl

curl 'https://rmws1976.xyz/search?q=%E4%B8%AD%E5%9B%BD&author=%E9%A9%AC%E5%85%8B%E6%80%9D&limit=5'
curl 'https://rmws1976.xyz/text?q=%E4%BA%9A%E7%BD%97%E5%8F%B7&author=%E9%A9%AC%E5%85%8B%E6%80%9D&limit=5'
curl 'https://rmws1976.xyz/article/7038'
curl 'https://rmws1976.xyz/author/%E9%A9%AC%E5%85%8B%E6%80%9D?limit=10'

附:字段速查

/search   query author authors scope verdict total count offset next_offset
          top_sim weak_floor lex_hits sub_hits results[]
          [scope_ignored] [date_ignored] [date_note]
results[] id title author date url summary tags sim match

/text     query author mode verdict total count hits_total
          scanned_chars took_ms results[] [note] [suggest_author]
results[] id title author date url hits match snippet tags

/article  id title author date url content tags

/author   author verdict total limit offset articles[]
articles[] id title date url