基于 Node.js 的 CSDN 文章列表获取代码解析
基于 Node.js 的 CSDN 文章列表获取代码解析
在开发过程中,与第三方 API 进行交互是常见的需求之一。本文将对一段用于获取 CSDN 文章列表的 Node.js 代码进行详细解析,帮助开发者理解其工作原理和实现细节。
代码功能概述
这段代码的主要功能是向 CSDN 的指定 API 发起 GET 请求,获取文章列表相关信息,包括文章的 ID、发布时间和标题等。在请求过程中,涉及到请求头部的处理、HMAC 签名的生成以及对 API 响应数据的解析和提取。
代码实现细节
1. 请求头部过滤
通过 filterHeaders 函数,从给定的请求头部对象中筛选出键名以 "x-ca-" 开头的头部信息。这些头部信息将在后续的签名生成过程中被用到。
const filterHeaders = (headers) => {
const filteredHeaders = {};
for (const key in headers) {
const lowerKey = key.toLowerCase();
if (lowerKey.startsWith("x-ca-")) {
filteredHeaders[lowerKey] = headers[key];
}
}
return filteredHeaders;
};
2. HMAC 签名生成
generateSignature 函数负责构建签名字符串并生成 HMAC 签名。签名字符串的构建过程如下:
- 依次添加请求方法、接受内容类型、空行、内容类型、日期。
- 处理请求头部,对筛选后的头部键进行排序,并按格式拼接到签名字符串中。
- 处理 URL 和参数,对参数键进行排序,构建查询字符串,并与处理后的 URL 拼接。
最后,使用 CryptoJS 库的 HmacSHA256 方法生成签名,并将其转换为 Base64 编码的字符串。
const generateSignature = ({ method, url, appSecret, accept, date, contentType, params, headers }) => {
let signatureString = `${method}\n${accept}\n\n${contentType}\n${date}\n`;
// 处理请求头部
const filteredHeaders = filterHeaders(headers);
const sortedHeaderKeys = Object.keys(filteredHeaders).sort();
for (const key of sortedHeaderKeys) {
signatureString += `${key}:${filteredHeaders[key]}\n`;
}
// 处理 URL 和参数
const processedUrl = url.replace(/^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.csdn\.net)/, "");
const urlParams = new URLSearchParams();
const sortedParamKeys = Object.keys(params).sort();
for (const key of sortedParamKeys) {
urlParams.append(key, params[key]);
}
signatureString += urlParams.toString() ? `${processedUrl}?${urlParams.toString()}` : processedUrl;
// 生成 HMAC 签名
return CryptoJS.HmacSHA256(signatureString, appSecret).toString(CryptoJS.enc.Base64);
};
3. 随机数生成
generateNonce 函数生成符合特定格式的随机数,用于请求的唯一标识。
const generateNonce = () => {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (char) => {
const random = (16 * Math.random()) | 0;
return (char === "x" ? random : (random & 3) | 8).toString(16);
});
};
4. 发起请求
在 fetchCSDNArticles 函数中,首先生成随机数,构建 API 请求配置。然后通过 generateSignature 函数获取签名,设置请求头部。最后,使用 axios 库发起 GET 请求,并对响应数据进行处理,提取文章列表相关信息。
async function fetchCSDNArticles() {
const nonce = generateNonce();
const apiConfig = {
method: 'GET',
url: 'https://bizapi.csdn.net/blog/phoenix/console/v1/article/list',
appSecret: 'xxxx',
accept: 'application/json, text/plain, */*',
date: '',
contentType: '',
params: {
page: 1,
pageSize: 100,
status: "all_v2"
},
headers: {
"Accept": "application/json, text/plain, */*",
"Content-Type": "",
"X-Ca-Key": "key",
'X-Ca-Nonce': nonce
}
};
const signature = generateSignature(apiConfig);
const requestHeaders = {
'cookie': `cookie`, // 需替换有效 cookie
'x-ca-key': apiConfig.headers['X-Ca-Key'],
'x-ca-nonce': nonce,
'x-ca-signature': signature,
"x-ca-signature-headers": "x-ca-key,x-ca-nonce",
};
try {
const response = await axios.get(apiConfig.url, {
headers: requestHeaders,
params: apiConfig.params
});
const articles = response.data.data.list.map(item => ({
id: item.articleId,
postTime: item.postTime,
title: item.title
}));
return articles;
} catch (error) {
console.error('请求失败:', error.response?.data || error.message);
return [];
}
}
使用示例
通过调用 fetchCSDNArticles 函数,并在其返回的 Promise 上使用 .then() 方法,可以获取到文章列表数据,并进行相应的处理和展示。
fetchCSDNArticles().then(articles => {
console.log('文章列表:', articles);
});
效果

注意事项
- 在实际使用中,需要将代码中的占位符(如 cookie 值)替换为有效的实际值,否则请求将无法通过验证。
- 由于网络环境或 CSDN API 的变动等因素,该代码可能无法直接运行成功。如果遇到问题,可以先检查网络连接、API 地址、参数配置等方面是否正确。
- CSDN 的 API 使用可能受到相关协议和规定的限制,请确保在合法合规的前提下使用该代码。
关于链接解析失败的说明
在代码中提到的链接 “https://bizapi.csdn.net/blog/phoenix/console/v1/article/list”,由于网络原因或链接本身的合法性问题,解析未能成功。如果您需要该网页的解析内容,请先检查网页链接的合法性和网络环境,适当重试。
免责声明
本文提供的代码仅供参考和学习,用于帮助开发者了解如何与 CSDN API 进行交互以及请求签名的生成过程。在实际使用中,请确保遵守 CSDN 的相关使用条款和规定,合法合规地使用其 API 服务。同时,代码中的部分参数(如 appSecret、apiKey、cookie 等)需要替换为实际有效的值才能正常运行,切勿使用未经授权的参数值。对于因使用本代码而引发的任何法律问题或纠纷,作者和发布平台不承担任何责任。