请求将R爬虫脚本转为可配置参数的JavaScript函数(VSCode环境)
解决Sikafinance数据爬取的JavaScript函数实现问题
我正在学习JavaScript,使用VSCode编辑器,需要把现有的R爬虫脚本转换成JS代码,实现循环获取全部可用数据的功能。目标是创建可配置ticker、datedeb、datefin、xperiod参数的函数,爬取Sikafinance网站对应BRVMAG数据页面的接口数据。
原R代码
library(httr2) library(magrittr) r <- request("https://www.sikafinance.com/api/general/GetHistos") %>% req_body_json(list('ticker'= 'BRVMAG', 'datedeb'= '2022-02-01', 'datefin'= '2022-03-29','xperiod'= '0')) %>% req_perform() %>% resp_body_json(simplifyVector = T)
现有JS代码及问题
我写的JS代码无法正常获取数据,主要问题有:
mode: "no-cors"会限制浏览器读取响应内容,导致无法解析返回的JSON- 硬编码了浏览器特定的
sec-ch-ua等请求头,这些不是接口必需的,反而可能引发问题 - 请求体用字符串拼接,不如直接传对象再序列化更易维护
- 重复定义了
method: "POST"
const options = { method: 'POST', headers: { "accept": "*/*", "accept-language": "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7", "content-type": "application/json;charset=UTF-8", "sec-ch-ua": "\"Chromium\";v=\"104\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"104\"", "sec-ch-ua-mobile": "?1", "sec-ch-ua-platform": "\"Android\"", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "same-origin" }, "referrer": "https://www.sikafinance.com/marches/historiques?s=BRVMAG", "referrerPolicy": "strict-origin-when-cross-origin", "body": "{\"ticker\":\"BRVMAG\",\"datedeb\":\"2022-06-19\",\"datefin\":\"2022-08-16\",\"xperiod\":\"0\"}", "method": "POST", "mode": "no-cors", "credentials": "include" }; fetch('https://www.sikafinance.com/api/general/GetHistos', options) .then(response => response.text()) .then(response => console.log(response)) .catch(err => console.error(err));
修复后的可配置参数函数
使用async/await语法编写更清晰的异步函数,简化请求头,正确处理请求体和响应:
/** * 获取Sikafinance历史数据的异步函数 * @param {string} ticker - 股票代码,如BRVMAG * @param {string} datedeb - 起始日期,格式YYYY-MM-DD * @param {string} datefin - 结束日期,格式YYYY-MM-DD * @param {string} xperiod - 周期参数,如"0" * @returns {Promise<Array>} 返回历史数据数组 */ async function getSikaFinanceHistos(ticker, datedeb, datefin, xperiod) { const url = 'https://www.sikafinance.com/api/general/GetHistos'; const options = { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify({ ticker, datedeb, datefin, xperiod }), credentials: 'include' }; try { const response = await fetch(url, options); if (!response.ok) throw new Error(`请求失败:${response.status}`); const data = await response.json(); return data; } catch (error) { console.error('获取数据出错:', error); throw error; } } // 示例调用 getSikaFinanceHistos('BRVMAG', '2022-02-01', '2022-03-29', '0') .then(data => console.log('获取到的数据:', data)) .catch(err => console.error(err));
循环获取全量数据实现
如果接口对单次请求的时间范围有限制,可按固定时间间隔拆分日期区间,循环请求后合并数据:
/** * 拆分日期区间为多个子区间 * @param {string} startDate - 起始日期YYYY-MM-DD * @param {string} endDate - 结束日期YYYY-MM-DD * @param {number} daysPerChunk - 每个子区间的天数 * @returns {Array<{start: string, end: string}>} 拆分后的日期区间数组 */ function splitDateRange(startDate, endDate, daysPerChunk = 30) { const start = new Date(startDate); const end = new Date(endDate); const chunks = []; let currentStart = new Date(start); while (currentStart <= end) { let currentEnd = new Date(currentStart); currentEnd.setDate(currentEnd.getDate() + daysPerChunk - 1); if (currentEnd > end) currentEnd = end; chunks.push({ start: currentStart.toISOString().split('T')[0], end: currentEnd.toISOString().split('T')[0] }); currentStart.setDate(currentEnd.getDate() + 1); } return chunks; } /** * 批量获取全量历史数据 * @param {string} ticker - 股票代码 * @param {string} startDate - 总起始日期 * @param {string} endDate - 总结束日期 * @param {string} xperiod - 周期参数 * @param {number} daysPerChunk - 每次请求的天数区间 * @returns {Promise<Array>} 合并后的全量数据 */ async function getAllSikaFinanceHistos(ticker, startDate, endDate, xperiod, daysPerChunk = 30) { const dateChunks = splitDateRange(startDate, endDate, daysPerChunk); const allData = []; for (const chunk of dateChunks) { console.log(`正在获取区间:${chunk.start} 至 ${chunk.end}`); try { const data = await getSikaFinanceHistos(ticker, chunk.start, chunk.end, xperiod); allData.push(...data); // 避免请求过于频繁,添加延迟 await new Promise(resolve => setTimeout(resolve, 1000)); } catch (error) { console.error(`获取区间${chunk.start}至${chunk.end}失败:`, error); } } return allData; } // 示例调用:获取2022年全年数据 getAllSikaFinanceHistos('BRVMAG', '2022-01-01', '2022-12-31', '0') .then(fullData => { console.log('全量数据获取完成,总条数:', fullData.length); // 可在这里处理或保存数据 }) .catch(err => console.error(err));
内容的提问来源于stack exchange,提问作者Koffi Frederic Sessie
相关产品推荐
相关产品推荐

