本文正在参加「Python主题月」,详情查看[活动链接]
序言
最近工作稳定了下来,手头上的闲钱也变多了,每天放在银行,收益小的不忍直视,每天上班的心情都没了,都在想着怎么提高收益。我在有一天午饭的时候看到了身边的同事各个都在买基金,顿时也想入这个坑了,真的是意识到了理财的重要性,每天下班了也不看什么源码、JVM这些课程了,而是开始去看一些B站的财经视频的科普。
要想分析基金,从几千只基金里面挑选出一只好基金,那肯定少不了历年的数据,作为一名程序员,为了分析方便,我还是觉得先把所有的数据爬下来,然后再做进一步处理。但是怎么获取数据处理数据呢?莫非是要一条条自己看,然后那笔写下来?达咩,这是不可能的。
我选取了爬虫这种比较常见的新兴技术,去简单学习了一下Python后就开始自己写爬虫程序开始,给爷爬!
分析
爬数据需要先思考从哪里爬?经过一番搜索和考虑,我发现天天基金网的数据既比较全,又十分容易爬取,所以就从它入手了。
我们随便选取一只去年的人气王—招商中证白酒(161725),上面有他的各种信息。
我使用的是chrome浏览器,按住F12可以进入到开发者模式,选择Network,在刷新一下就可以看到普通人看不到的一面。我们在Network下面拉一点可以看到基金代码.js?v开头的,点开他可以看到旁边的URL请求地址:http://fund.eastmoney.com/pingzhongdata/161725.js?v=20210719125054,也就是说我们可以简单的通过http://fund.eastmoney.com/pingzhongdata/基金代码.js?v=当前时间这样一个接口就能获取到相应的数据了。
我们点开旁边的Preview,我滴乖乖,原来我们需要的数据都藏在这里。
开始实战
引入模块
现在接口有了,数据分析也有了,就是http://fund.eastmoney.com/pingzhongdata/基金代码.js?v=当前时间
通过基金代码和当前时间我们就能够获取到相应的数据,接下来就是需要将我们想要的数据从获取的文件中提取出来了,也就是我们说的数据清洗的过程。
这个网站提供的数据不是常见的json格式,因此提取会有点麻烦,比如通过字符串查找等,但是由于这个是js文件,因此,我找到了更合适的方法——利用了PyExecJs模块就能很方便地编译解析js代码啦。
首先我们需要在终端安装PyExecJs这个模块。
pip install PyExecJs
然后引入这些模块
import requests
import time
import execjs
接口构造
def getUrl(fscode):
head = 'http://fund.eastmoney.com/pingzhongdata/'
tail = '.js?v='+ time.strftime("%Y%m%d%H%M%S",time.localtime())
return head+fscode+tail
获取净值
def getWorth(fscode):
#用requests获取到对应的文件
content = requests.get(getUrl(fscode))
#使用execjs获取到相应的数据
jsContent = execjs.compile(content.text)
name = jsContent.eval('fS_name')
code = jsContent.eval('fS_code')
#单位净值走势
netWorthTrend = jsContent.eval('Data_netWorthTrend')
#累计净值走势
ACWorthTrend = jsContent.eval('Data_ACWorthTrend')
netWorth = []
ACWorth = []
#提取出里面的净值
for dayWorth in netWorthTrend[::-1]:
netWorth.append(dayWorth['y'])
for dayACWorth in ACWorthTrend[::-1]:
ACWorth.append(dayACWorth[1])
print(name,code)
return netWorth, ACWorth
查看数据
这样我们就可以通过基金代码来查到对应的数据啦。
netWorth, ACWorth = getWorth('161725')
print(netWorth)
我们可以看到结果确实没错,第一个就是今天的单位净值。
当然,我们也可以自己画一个走势图来验证一下。
import matplotlib.pyplot as plt
plt.figure(figsize=(10,5))
plt.plot(netWorth[:60][::-1])
plt.show()
下面给出源代码。
import requests
import time
import execjs
import matplotlib.pyplot as plt
def getUrl(fscode):
head = 'http://fund.eastmoney.com/pingzhongdata/'
tail = '.js?v='+ time.strftime("%Y%m%d%H%M%S",time.localtime())
return head+fscode+tail
def getWorth(fscode):
#用requests获取到对应的文件
content = requests.get(getUrl(fscode))
#使用execjs获取到相应的数据
jsContent = execjs.compile(content.text)
name = jsContent.eval('fS_name')
code = jsContent.eval('fS_code')
#单位净值走势
netWorthTrend = jsContent.eval('Data_netWorthTrend')
#累计净值走势
ACWorthTrend = jsContent.eval('Data_ACWorthTrend')
netWorth = []
ACWorth = []
#提取出里面的净值
for dayWorth in netWorthTrend[::-1]:
netWorth.append(dayWorth['y'])
for dayACWorth in ACWorthTrend[::-1]:
ACWorth.append(dayACWorth[1])
print(name,code)
return netWorth, ACWorth
netWorth, ACWorth = getWorth('161725')
plt.figure(figsize=(10,5))
plt.plot(netWorth[:60][::-1])
plt.show()
获取所有基金数据
这里我通过同样的方式,找到了所有基金列表的接口。 通过'http://fund.eastmoney.com/js/fundcode_search.js'便可以直接获取到所有的基金代码,再通过基金代码可以遍历爬取所有基金的数据,我将下载的数据存成了csv,方便excel打开或用代码读取。
import requests
import time
import execjs
def getUrl(fscode):
head = 'http://fund.eastmoney.com/pingzhongdata/'
tail = '.js?v='+ time.strftime("%Y%m%d%H%M%S",time.localtime())
return head+fscode+tail
# 根据基金代码获取净值
def getWorth(fscode):
content = requests.get(getUrl(fscode))
jsContent = execjs.compile(content.text)
name = jsContent.eval('fS_name')
code = jsContent.eval('fS_code')
#单位净值走势
netWorthTrend = jsContent.eval('Data_netWorthTrend')
#累计净值走势
ACWorthTrend = jsContent.eval('Data_ACWorthTrend')
netWorth = []
ACWorth = []
for dayWorth in netWorthTrend[::-1]:
netWorth.append(dayWorth['y'])
for dayACWorth in ACWorthTrend[::-1]:
ACWorth.append(dayACWorth[1])
print(name,code)
return netWorth, ACWorth
def getAllCode():
url = 'http://fund.eastmoney.com/js/fundcode_search.js'
content = requests.get(url)
jsContent = execjs.compile(content.text)
rawData = jsContent.eval('r')
allCode = []
for code in rawData:
allCode.append(code[0])
return allCode
allCode = getAllCode()
netWorthFile = open('./netWorth.csv','w')
ACWorthFile = open('./ACWorth.csv','w')
for code in allCode:
try:
netWorth, ACWorth = getWorth(code)
except:
continue
if len(netWorth)<=0 or len(ACWorth)<0:
print(code+"'s' data is empty.")
continue
netWorthFile.write("\'"+code+"\',")
netWorthFile.write(",".join(list(map(str, netWorth))))
netWorthFile.write("\n")
ACWorthFile.write("\'"+code+"\',")
ACWorthFile.write(",".join(list(map(str, ACWorth))))
ACWorthFile.write("\n")
print("write "+code+"'s data success.")
netWorthFile.close()
ACWorthFile.close()