做内容类产品时,热点数据很适合用来补首页的“更新感”。对我这次的项目来说,我需要的不是一个单纯返回关键词的接口,而是一份能直接进入榜单模块、推荐区和热点流的数据源。

我最后接的是百度热搜榜 API。相比照着文档把字段解释一遍,我更想把这篇文章写成一次真实的工程接入:它在项目里解决了什么、我为什么选它、以及我怎么把它整理成前端真正好消费的数据结构。

这份榜单数据正好补上了内容入口

我这次接热榜接口,核心目标很明确:给内容系统补一层会随着时间变化的数据。只要首页多一块热点榜单,页面的动态感和点击意愿都会明显更强,这对内容聚合、资讯流和热点推荐都很有帮助。

百度热搜榜 API 对我最实用的地方,在于它返回的是已经适合直接展示的榜单项。像标题、排名、热度、详情链接、配图这些信息,本身就足够拼出一个榜单区块,不需要我再去做额外抓取。

我在项目里主要把它用在三个位置:

  • 首页热点流
  • 热点追踪页
  • 运营推荐区

所以我不是把它当成“热词查询接口”来接,而是把它当成一层轻量内容源来用。

我为什么直接选了它

我用的是百度热搜榜 API,接口地址是 https://v1.apizero.cn/api/hot-baidu,文档我直接参考的是它提供的 AI 接入说明:https://apizero.cn/aidocs/hot-baidu/raw.md

我最后选它,原因主要有三个。

第一,入口统一。不同榜单类型都走同一个接口,我只需要通过 tab 切换,就能把实时热搜这类数据挂进同一个服务层。对后端来说,这种接口形态很好封装,controller 和 service 不需要为每个榜单拆多套逻辑。

第二,返回结果足够贴近页面需求。榜单项里已经带有标题、摘要、热度、跳转链接和图片,我不需要再做一层重处理,就能把数据接到榜单卡片或者热点列表里。

第三,适合先接进项目再做增强。对内容型接口来说,我更在意的是先把能力落地,再慢慢补缓存、推荐策略和运营能力。这个接口很适合这种节奏,先接入、先上线、再围绕业务打磨。

我的接入做法

我没有让前端直接请求第三方接口,而是在自己后端包了一层。这样做的目的很简单:前端拿到的永远是我业务里定义好的结构,后面不管我补缓存、换字段名,还是增加别的榜单源,页面层都不用跟着改。

我的后端只做三件事:

  • 校验榜单类型
  • 请求第三方接口
  • 整理返回字段

先看我在项目里采用的调用链路:

前端请求

后端校验

请求热榜

整理字段

返回列表

这个流程很短,但职责已经很清楚了。前端只负责告诉后端要哪个榜单,后端负责把第三方数据转成自己的输出结构。这样前端不用关心第三方字段命名,也不用处理不同榜单下可选字段不一致的问题。

下面这段代码就是我在首版里保留下来的核心封装。它不追求复杂,而是尽量做到复制过去就能跑:

import axios from "axios";

const client = axios.create({
  baseURL: "https://v1.apizero.cn/api",
  timeout: 5000,
});

export async function fetchBaiduHot(tab = "realtime") {
  try {
    const safeTab = ["realtime", "novel", "movie", "tv"].includes(tab)
      ? tab
      : "realtime";

    const { data } = await client.get("/hot-baidu", {
      params: { tab: safeTab },
    });

    if (data?.code !== 0 || !Array.isArray(data?.data?.list)) {
      throw new Error(data?.msg || "request failed");
    }

    return data.data.list.map((item: any) => ({
      rank: item.rank,
      title: item.title,
      summary: item.desc || "",
      hot: item.hot_index || 0,
      link: item.link,
      image: item.image || "",
      tag: item.tag || "",
    }));
  } catch (err) {
    console.error("fetch baidu hot failed:", err);
    return [];
  }
}

fetchBaiduHot("realtime").then((list) => {
  console.log(list.slice(0, 3));
});

这段代码里我刻意只保留了最核心的动作:发请求、控超时、收结果、给前端一个稳定结构。真实项目里我会再补缓存和监控,但首版接入时,先把调用函数和输出结构定下来更重要。

返回字段我只保留了页面真正会用的部分

第三方接口返回的信息并不少,但我没有选择原样透传。我的处理原则是:页面真正用什么,我就保留什么;先把结构收紧,后面维护起来会轻很多。

我最终固定保留的是这些字段:

  • rank
  • title
  • desc
  • hot_index
  • link
  • image
  • tag

这几个字段已经足够支撑大多数热点展示场景。首页榜单关心的是排第几、标题是什么、热度高不高、点进去去哪儿;推荐卡片关心的是标题、配图和跳转链接。只保留这些核心字段,前端渲染逻辑会更直接,落库结构也更干净。

另外我顺手做了一层命名整理。比如把 desc 改成 summary,把 hot_index 改成 hot。这种转换不复杂,但它能让 service、接口返回和前端类型定义统一起来,后面读代码也舒服很多。

两个做完之后会明显顺手的小细节

我把超时压到了 5 秒

这类热点接口适合追求“快而稳”的体验,所以我的做法是把超时直接设成 5 秒,而不是让请求长时间挂着。这样就算第三方接口偶尔慢一点,也不会把首页整体响应拖住。

对内容型页面来说,这种处理很实用。因为用户更在意页面能不能尽快打开,而不是一定要等一份最新结果。后面如果需要,我再配一层简单缓存,就能让二次访问更顺。

我在入口层先把榜单类型收紧了

接口支持的榜单类型其实很明确,所以我没有把参数检查放到请求失败之后,而是在入口层先把 tab 限定住。传对了就正常走,传错了就回到默认榜单。

这种处理看起来很小,但能让服务表现更稳定。前端、运营后台、定时任务都可能会传参,只要入口层先收住,后面的逻辑就会简单很多。

这些场景接上去最容易见到效果

如果你做的是内容聚合、资讯流、热点推荐、娱乐频道或者榜单页,这个接口会很顺手。它特别适合那种页面需要持续变化,但又不想先搭完整内容采集链路的项目。

不过它也有边界。我的理解是,它更适合做热点入口、榜单补充和内容增强,不适合承担完整的个性化分发职责。因为它解决的是“现在什么热”,但不负责“这条内容和当前用户是不是最匹配”。

另外,如果你的页面非常依赖完整详情结构,比如长文本正文、深度结构化内容或者强业务字段关联,那这类热榜接口也更适合作为入口层,而不是唯一内容源。拿它来做发现和引流很合适,真正的内容沉淀还是要落回你自己的业务体系里。


4. 后端封装代码

import axios from "axios";

const client = axios.create({
  baseURL: "https://v1.apizero.cn/api",
  timeout: 5000,
});

export async function getBaiduHot(tab = "realtime") {
  try {
    const safeTab = ["realtime", "novel", "movie", "tv"].includes(tab)
      ? tab
      : "realtime";

    const { data } = await client.get("/hot-baidu", {
      params: { tab: safeTab },
    });

    if (data?.code !== 0 || !Array.isArray(data?.data?.list)) {
      throw new Error(data?.msg || "request failed");
    }

    return {
      tab: safeTab,
      updateTime: data.data.update_time,
      list: data.data.list.map((item: any) => ({
        rank: item.rank,
        title: item.title,
        summary: item.desc || "",
        hot: item.hot_index || 0,
        link: item.link,
        image: item.image || "",
        tag: item.tag || "",
      })),
    };
  } catch (err) {
    console.error("getBaiduHot error:", err);
    return { tab, updateTime: "", list: [] };
  }
}

getBaiduHot("realtime").then((res) => {
  console.log(res.list.slice(0, 5));
});
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐