哼哼猫文档
本页内容

JavaScript 代码示例

Node 18 起内置了 fetch,调这套接口不装任何依赖就能跑;项目里已经在用 axios 的,直接用 axios 也一样。

本页给三段可以直接抄的代码:Promise 链写法的 fetch、axios,以及最接近生产用法的 async/await 封装。API Key 只能放在服务端——写进前端页面等于把它公开出去,浏览器里需要提取能力时应该由自己的后端转发一次。

🚀 使用 Fetch API

最短的能跑通的写法,Node 与浏览器里的 API 一致。fetch 有一处和别的 HTTP 库都不同:400、401、429 都不会让它 reject,只有 DNS 解析、连接失败这类网络层错误才会,所以必须先判断 response.ok,否则会拿着错误体去读 data.medias。错误体同样是 JSON,要再 .json() 一次才能读到 code 与 retryable。

响应里 title 与 text 都是可选字段,两个可能同时有、也可能只有 text,展示文案写 data.title || data.text 就够;媒体清单在 medias,每个媒体的可选清晰度在 variants 里,is_default 为 true 的那档是推荐值。video_url 与 audio_url 同时出现说明是音视频分离的流,两条都要下载再合并。

const apiUrl = "https://api.meowload.net/openapi/v1/extract/post";
const apiKey = "<你的 API Key>";

fetch(apiUrl, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Authorization": `Bearer ${apiKey}`,
    "Accept-Language": "zh"
  },
  body: JSON.stringify({
    url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  })
})
  .then(response => {
    if (!response.ok) {
      // 400 的错误体带 code 与 retryable
      return response.json().then(error => {
        throw Object.assign(new Error(`${response.status}: ${error.message}`), {
          code: error.code,
          retryable: error.retryable === true
        });
      });
    }
    return response.json();
  })
  .then(data => {
    // title 与 text 都是可选的:有标题的平台取 title,其余取 text
    console.log(`✅ 提取成功,平台: ${data.site},文案: ${data.title || data.text || "无"}`);

    data.medias.forEach(media => {
      console.log(`- ${media.media_type}: ${media.resource_url}`);
      // 多清晰度 / 多音轨在 variants 里;video_url 与 audio_url 同时存在表示音视频分离
      for (const variant of media.variants ?? []) {
        const split = variant.video_url && variant.audio_url ? "(需合并)" : "";
        console.log(`    ${variant.quality_label ?? "默认"}${split}`);
      }
    });
  })
  .catch(error => {
    console.error(`❌ 请求失败: ${error.message}`);
    if (error.retryable) console.error(`   错误码 ${error.code} 是临时失败,可稍后重试`);
  });

📦 使用 Axios(Node.js)

项目里已有 axios,或者想用拦截器统一加请求头、统一记日志时用这段。和 fetch 相反,axios 会把非 2xx 直接扔进 catch,但错误详情在 error.response.data 里而不是 error.message——只打印 error.message 会得到一句没有信息量的「Request failed with status code 400」。

error.response 为空表示请求根本没拿到响应(超时、连接被拒)。axios 默认不设超时,生产代码建议显式配 timeout,并对 429 和 retryable 为 true 的错误做退避重试。

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

const apiUrl = "https://api.meowload.net/openapi/v1/extract/post";
const apiKey = "<你的 API Key>";

axios.post(apiUrl, {
  url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}, {
  headers: {
    "Authorization": `Bearer ${apiKey}`,
    "Accept-Language": "zh"
  }
})
  .then(response => {
    const data = response.data;
    console.log(`✅ 提取成功,平台: ${data.site},文案: ${data.title || data.text || "无"},媒体数量: ${data.medias.length}`);
  })
  .catch(error => {
    if (error.response) {
      const { status, data } = error.response;
      console.error(`❌ 请求失败 (${status}): ${data.message}`);
      // 400 带 code 与 retryable;429 需退避重试
      if (data.retryable) console.error(`   错误码 ${data.code} 是临时失败,可稍后重试`);
    } else {
      console.error(`❌ 网络错误: ${error.message}`);
    }
  });

🎯 使用 async/await

真正会放进项目里的形态:把提取包成一个函数,成功返回数据,失败抛一个带 status、code、retryable 的错误,调用方在一处决定要不要重试。这里先 await response.json() 再判断 response.ok,是因为成功体和错误体都是 JSON,一次解析两边都能用。

要注意代理或中间层返回的错误页未必是 JSON,json() 会抛解析错误,生产代码可以先看 content-type 或包一层 try。拿到结果后媒体直链要尽快下载,它是短效的,别存进数据库当长期地址用。

async function extractPost(url, apiKey) {
  const response = await fetch("https://api.meowload.net/openapi/v1/extract/post", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${apiKey}`
    },
    body: JSON.stringify({ url })
  });

  const data = await response.json();
  if (!response.ok) {
    // 把 code 与 retryable 带出去,调用方据此决定要不要重试
    throw Object.assign(new Error(data.message), {
      status: response.status,
      code: data.code,
      retryable: data.retryable === true
    });
  }
  return data;
}

// 使用
try {
  const result = await extractPost("https://www.youtube.com/watch?v=dQw4w9WgXcQ", "<你的 API Key>");
  console.log(`✅ ${result.title || result.text || "无"},媒体数量: ${result.medias.length}`);
} catch (error) {
  console.error(`提取失败: ${error.message}${error.retryable ? "(可稍后重试)" : ""}`);
}

接着可以看这几页: