一、为什么需要随机诗词 API?

在技术产品中融入传统文化已成为提升用户体验的常见手段。无论是登录页的每日诗词、分享卡片上的金句,还是社交动态里的背景文字,随机诗词 API 都能让应用瞬间拥有“书卷气”。然而,自行整理诗词库、管理版权、实现随机逻辑非常繁琐。调用一个稳定、免费、文档完善的随机诗词 API 是最省力的方案。

本文以 极数本源 (ApiZero) 提供的随机诗词接口为例,手把手带你完成从 API 调研到前端卡片生成的全流程。所有代码均可直接运行,你只需复制粘贴即可在自己的项目中复用。

二、API 接口概览

假设我们使用的接口地址为:

https://api.apizero.cn/marketplace/shici/random

(实际端点以官方文档为准,此处为演示构造)

请求方式:GET

无需 API Key(公开接口),返回 JSON 格式:

{
  "code": 200,
  "msg": "success",
  "data": {
    "title": "静夜思",
    "author": "李白",
    "dynasty": "唐",
    "content": "床前明月光,疑是地上霜。举头望明月,低头思故乡。",
    "notes": "通过月光表达思乡之情"
  }
}

字段说明:

字段名 类型 说明
code int 状态码,200 表示成功
msg str 提示信息
data object 诗词数据主体
data.title str 诗词标题
data.author str 作者
data.dynasty str 朝代
data.content str 正文(含标点)
data.notes str 赏析或备注(可选)

三、用 curl 快速验证

在终端中执行以下命令即可获取一首随机诗词:

curl -s https://api.apizero.cn/marketplace/shici/random | jq .

如果未安装 jq,直接去掉 | jq . 也能看到原始 JSON。输出示例:

{"code":200,"msg":"success","data":{"title":"登鹳雀楼","author":"王之涣","dynasty":"唐","content":"白日依山尽,黄河入海流。欲穷千里目,更上一层楼。","notes":"寓意登高望远"}}

这一步主要用于确认接口可用、网络连通、数据格式符合预期。

四、Python 调用:获取诗词并解析

使用 requests 库,安装方式:

pip install requests

完整示例代码:

import requests

def get_random_poem() -> dict:
    url = "https://api.apizero.cn/marketplace/shici/random"
    try:
        resp = requests.get(url, timeout=10)
        resp.raise_for_status()  # 检查 HTTP 状态码
        data = resp.json()
        if data.get("code") == 200:
            return data["data"]
        else:
            raise Exception(f"API 返回异常: {data.get('msg')}")
    except requests.exceptions.RequestException as e:
        print(f"网络请求失败: {e}")
        return {}

if __name__ == "__main__":
    poem = get_random_poem()
    if poem:
        print(f"《{poem['title']}》——{poem['author']}({poem['dynasty']})")
        print(poem["content"])
        if poem.get("notes"):
            print(f"赏析: {poem['notes']}")
    else:
        print("获取诗词失败")

运行输出示例:

《将进酒》——李白(唐)
君不见黄河之水天上来,奔流到海不复回……
赏析: 劝酒放歌,豪迈奔放

4.1 错误处理要点

  • 网络超时:设置 timeout 避免阻塞。
  • 状态码非 200:可能是接口限流或临时故障,建议重试或降级。
  • JSON 解析异常:用 try...except 捕获 json.JSONDecodeError
  • API 返回的 code 非 200:表示业务错误,需要根据 msg 处理。

五、JavaScript 调用:在浏览器或 Node.js 中使用

5.1 浏览器端(fetch)

在 HTML 中直接使用:

async function fetchRandomPoem() {
  const url = "https://api.apizero.cn/marketplace/shici/random";
  try {
    const response = await fetch(url);
    if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
    const result = await response.json();
    if (result.code === 200) {
      return result.data;
    } else {
      throw new Error(result.msg);
    }
  } catch (error) {
    console.error("获取诗词失败:", error);
    return null;
  }
}

5.2 Node.js 端(axios)

安装 axios:

npm install axios
const axios = require('axios');

async function getRandomPoem() {
  try {
    const response = await axios.get('https://api.apizero.cn/marketplace/shici/random', { timeout: 10000 });
    if (response.data.code === 200) {
      return response.data.data;
    } else {
      throw new Error(response.data.msg);
    }
  } catch (error) {
    console.error('API 请求失败:', error.message);
    return null;
  }
}

六、实战项目:诗词卡片生成器

将上述 API 与前端渲染结合,实现一个实时生成精美诗词卡片的工具。

6.1 项目结构

poem-card-generator/
├── index.html
├── style.css
├── script.js
└── README.md

6.2 静态页面 (index.html)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>随机诗词卡片生成器</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="container">
    <div id="card" class="card">
      <div class="card-header">
        <h2 id="title">静夜思</h2>
        <p id="author">李白 · 唐</p>
      </div>
      <div id="content" class="card-body">床前明月光,疑是地上霜。</div>
      <div id="notes" class="card-footer">赏析:通过月光表达思乡之情</div>
    </div>
    <button id="refreshBtn">换一首诗</button>
  </div>
  <script src="script.js"></script>
</body>
</html>

6.3 CSS 样式 (style.css)

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  font-family: 'KaiTi', 'STKaiti', serif;
}

.container {
  text-align: center;
}

.card {
  background: #fff;
  border-radius: 16px;
  box-shadow: 0 8px 32px rgba(0,0,0,0.12);
  padding: 40px 30px;
  max-width: 500px;
  min-height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  transition: all 0.3s ease;
}

.card-header h2 {
  font-size: 28px;
  color: #333;
  margin-bottom: 8px;
}

.card-header p {
  color: #888;
  font-size: 16px;
  margin-bottom: 20px;
}

.card-body {
  font-size: 22px;
  line-height: 1.8;
  color: #2c3e50;
  white-space: pre-line;
  text-align: center;
  margin-bottom: 15px;
}

.card-footer {
  font-size: 14px;
  color: #666;
  font-style: italic;
  border-top: 1px solid #eee;
  padding-top: 12px;
  width: 100%;
}

#refreshBtn {
  margin-top: 30px;
  padding: 12px 40px;
  font-size: 18px;
  border: none;
  border-radius: 30px;
  background: #667eea;
  color: white;
  cursor: pointer;
  transition: background 0.3s;
}

#refreshBtn:hover {
  background: #5a67d8;
}

6.4 JavaScript 逻辑 (script.js)

async function loadPoem() {
  const titleEl = document.getElementById('title');
  const authorEl = document.getElementById('author');
  const contentEl = document.getElementById('content');
  const notesEl = document.getElementById('notes');

  // 显示加载状态
  contentEl.textContent = '正在生成诗词...';

  try {
    const response = await fetch('https://api.apizero.cn/marketplace/shici/random');
    if (!response.ok) throw new Error('网络异常');
    const result = await response.json();
    if (result.code !== 200) throw new Error(result.msg);

    const poem = result.data;
    titleEl.textContent = `《${poem.title}》`;
    authorEl.textContent = `${poem.author} · ${poem.dynasty}`;
    contentEl.textContent = poem.content;
    notesEl.textContent = poem.notes ? `赏析:${poem.notes}` : '';
  } catch (error) {
    contentEl.textContent = '获取诗词失败,请稍后重试';
    console.error(error);
  }
}

// 点击换一首诗
document.getElementById('refreshBtn').addEventListener('click', loadPoem);

// 页面加载时自动获取一首
window.addEventListener('DOMContentLoaded', loadPoem);

6.5 效果预览

打开 index.html 即可看到一张白色卡片,显示随机诗词。点击“换一首诗”按钮,异步获取新诗词并更新卡片内容。整个过程无刷新,体验流畅。

七、进阶:服务端缓存与降级策略

在生产环境中,直接调用第三方 API 存在依赖风险。建议加入以下优化:

  • 本地缓存:在 Redis 或内存中缓存最新 10 首诗词,优先从缓存取,API 失败时返回缓存版本。
  • 定时预取:每 5 分钟主动拉取一批诗词入库,减少实时请求。
  • 多 API 源:准备备用诗词 API,当主接口超时时切换。

Python 实现简单缓存示例:

import requests
import time

class PoemCache:
    def __init__(self, ttl=300):
        self.cache = []
        self.ttl = ttl
        self.last_fetch = 0

    def get(self):
        if time.time() - self.last_fetch > self.ttl or not self.cache:
            self._refresh()
        # 随机返回一首
        import random
        return random.choice(self.cache)

    def _refresh(self):
        try:
            resp = requests.get('https://api.apizero.cn/marketplace/shici/random', timeout=5)
            if resp.status_code == 200:
                data = resp.json()
                if data['code'] == 200:
                    self.cache.append(data['data'])
                    self.last_fetch = time.time()
        except Exception as e:
            print(f"刷新缓存失败: {e}")

八、总结

通过本文的学习,你掌握了:

  1. 阅读和理解随机诗词 API 的接口文档。
  2. 使用 curl、Python requests、JavaScript fetch 三种方式调用 API。
  3. 处理常见网络和业务错误。
  4. 结合前端技术构建一个完整的诗词卡片生成器。
  5. 设计服务端缓存和降级策略提升稳定性。

随机诗词 API 是一个小巧但极具文化韵味的公共接口。你可以在博客侧栏、移动端启动图、个人主页等场景中灵活运用它。代码已全部给出,记得替换为真实的 API 端点即可。

如果你还有其他创意(比如将诗词生成 SVG 配图、对接语音朗读),欢迎在评论区分享。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐