- 众所周知,我们来写代码本质上是为了搞钱,既然写代码是我们工作的饭碗,能不能成为我们做其他副业的饭碗呢,我沉思了很久,觉得可以。
- 看着周围同学朋友们买基金赚了钱,我很难不心动,作为一名前端开发,当然得用前端开发的手段来挑选合适的基金,碰巧这个季度我们组有个关于Deno的分享,于是我选择了Deno进行爬取基金数据。当然了对于Deno的安装这里就不多谈了。
下面进入正文
- 如何选择合适的基金,按照我朋友的说法
- 买基金要看长远点,要看三年以上的收益率,这样才能看出这个基金的稳定性。
- 基金规模也尽量大一点,因为太小的规模的基金一方面说明了募集资金的能力不强,也就是说基金并不被大众认可,规模大一点的基金也因为规模大只能买大市值的公司,也极大的减少了风险。能管理大规模的基金的基金经理也必然是优胜劣汰出来的。
- 基金成立时间要长,其实市场上的基金数量已经远远大于股票数量了,而基金也会因业绩不行倒闭或者因公司发展而关闭,买成立时间长的也是为了稳定,毕竟风险第一,收益第二
- 基金经理在职久一点,因为基金的收益很大一部分原因是和基金经理挂钩,毕竟买基金就是买基金经理
- 现在我们的目标已经有了,就是满足上面的条件的基金,我以我个人的喜好选择了,近三年收益率大于100%,且成立时间在7年以上,且资金规模大于10亿的,且基金经理在职3年以上的基金公司。
- 作为雪球资深用户,我挑选了蛋卷基金网站进行爬取,网站地址为:danjuanfunds.com/rank/perfor…
- 这个页面可以按照收益率排行,我们可以按照近三年进行筛选,看了下近三年收益率排行榜接口是这样的
const SIZE = 500; // 前500个基金
const page = 1;
const TYPE = 1
const order_by = '3y'
const url = `https://danjuanfunds.com/djapi/v3/filter/fund?type=${TYPE}&order_by=${order_by}&size=${SIZE}&page=${page}`
复制代码
- 由于Deno是自带fetch的,所以不用特地引入fetch了,请求接口的代码如下:
// 基金的id数组
const fundIdList = []
fetch(url, headers)
.then(function(res) {
return res.json();
})
.then(function(myJson) {
const resData = myJson.data
resData.items.forEach((item,index) => {
// 挑选近三年收益率>100%的基金id
if (Number(item.yield) >= 100) {
fundIdList.push(item.fd_code);
}
})
});
复制代码
- 挑选出来了优秀基金的id之后,我们去查询基金id的详情,详情的页面地址是这样的:danjuanfunds.com/funding/011… 接口地址是这样的:danjuanfunds.com/djapi/fund/…
- 那么我们就可以从上面的id列表去请求数据了,请求基金详情的代码是这样的:
const getFundDetail = (id) => {
const url = `https://danjuanfunds.com/djapi/fund/${id}` // 接口
return fetch(url).then(function(res) {
return res.json();
});
}
复制代码
- 我们循环去请求基金列表中的基金详情,代码如下:
const getAllFundData = async () => {
// 获取所有的基金ID
await getFundList();
// 循环请求接口获取基金详情并过滤
for (let i = 0; i < fundIdList.length; i++) {
const id = fundIdList[i]
const myJson = await getFundDetail(id)
const managerDetail = await getManagerDetail(id)
const managerList = managerDetail.data.manager_list.length && managerDetail.data.manager_list[0]
// 基金经理管理时间
const keepTime = managerList.achievement_list.filter((item) => {
return item.fund_code === id
})[0]?.post_date
const fundDetail = getFilterData({...myJson, keepTime})
const total = fundDetail.totalMoney.split('亿');
// 成立超过7年的基金
const fundTime = 1000 * 60 * 60 * 24 * 30 * 12 * 7
// 基金经理在职时间
const manegeTime = 1000 * 60 * 60 * 24 * 30 * 12 * 3
const nowTime = new Date().getTime()
const startTime = new Date(fundDetail.startDate).getTime()
const keepTimeStamp = new Date(keepTime).getTime()
if (nowTime - startTime > fundTime && total[0] && total[0] > 10 && nowTime - keepTimeStamp > manegeTime) {
goodFundList.push(fundDetail)
}
}
writeJson('./fundData.json', goodFundList)
const endTime = new Date().getTime()
console.log('-----deno--文件之后消耗时间', endTime - startTime)
}
复制代码
- 获取基金经理方法如下
const getManagerDetail = (id) => {
const url = `https://danjuanfunds.com/djapi/fund/detail/${id}` // 接口
return fetch(url).then(function(res) {
return res.json();
});
}
复制代码
- 过滤基金数据方法:
/**
* 过滤基金数据
*/
const getFilterData = (myJson) => {
const resData = myJson.data
const startDate = resData.found_date // 开始时间
const code = resData.fd_code // 代码
const manager = resData.manager_name // 基金经理
const totalMoney = resData.totshare // 金钱规模
const fullName = resData.fd_full_name // 基金的名字
const company = resData.keeper_name // 公司名字
const fundDerived = resData.fund_derived // 收益
const unitNav = fundDerived.unit_nav // 历史累计收益
const keepTime = myJson.keepTime // 管理时间
const fundDetail = {
startDate,code,manager,totalMoney,fullName,company,unitNav, fundDerived,keepTime
}
return fundDetail
}
复制代码
- 最后当然是把我们爬取的数据放入文件中,便于我们查看基金数据啦:
function writeJson(path, data) {
try {
const endTime = new Date().getTime()
console.log('-----deno--消耗时间', endTime - startTime)
Deno.writeTextFileSync(path, JSON.stringify(data));
return "Written to " + path;
} catch (e) {
return e.message;
}
}
复制代码
- 最后爬取的基金数据会写入fundData.json文件中,然后我推荐可以使用在线json转excel,可以使爬取的数据更加的简洁明了,网站地址:uutool.cn/json2excel/
最后跑出来的基金是这样的:
- 温馨提示
- 基金有风险,买入须谨慎
- 爬虫的时候建议不要太频繁,把对方网站搞挂了也是有风险的
- 可以根据自己喜好调整筛选基金条件,当然你可以设置1000%的收益率
最后就是代码的链接了,可能很多人没有安装Deno环境,顺便附上node版本的爬虫
- github地址:github.com/wayofwade/d…