基于 Node.js 的 CSDN 文章列表获取代码解析
在开发过程中,与第三方 API 进行交互是常见的需求之一。本文将对一段用于获取 CSDN 文章列表的 Node.js 代码进行详细解析,帮助开发者理解其工作原理和实现细节。
代码功能概述
这段代码的主要功能是向 CSDN 的指定 API 发起 GET 请求,获取文章列表相关信息,包括文章的 ID、发布时间和标题等。在请求过程中,涉及到请求头部的处理、HMAC 签名的生成以及对 API 响应数据的解析和提取。
代码实现细节
1. 请求头部过滤
通过 filterHeaders
函数,从给定的请求头部对象中筛选出键名以 "x-ca-" 开头的头部信息。这些头部信息将在后续的签名生成过程中被用到。
javascriptconst 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 编码的字符串。
javascriptconst 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
函数生成符合特定格式的随机数,用于请求的唯一标识。
javascriptconst 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 请求,并对响应数据进行处理,提取文章列表相关信息。
javascriptasync 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()
方法,可以获取到文章列表数据,并进行相应的处理和展示。
javascriptfetchCSDNArticles().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 等)需要替换为实际有效的值才能正常运行,切勿使用未经授权的参数值。对于因使用本代码而引发的任何法律问题或纠纷,作者和发布平台不承担任何责任。