这篇文章主要为大家分享对基金数据的爬取,并通过python对获取的基金数据做一定的数据分析,如净值数据绘图,周均值,月均值的计算,及搜寻处于下降态势的基金,通过这些方法能对基金的买入与卖出提供一定的辅助作用!最后还是建议大家尽量不要盲目相信数据分析结果或者群众引导而进行买入和卖出,一定要结合自身对该基金或者股票的思考来考虑是否进行买入和卖出操作。
目录
1.基金数据爬取
1.工具准备:
在此主要应用python进行爬虫,主要会应用的包如下:
from bs4 import BeautifulSoup #进行网页解析获取数据
import re #正则表达式,进行文字匹配
import urllib.request,urllib.error #制定URL。获取网页数据
import xlwt #进行excel操作
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import random
import xlrd
其中bs4包主要用于网页解析数据,re包用于语言正则化,用requests来获取网页数据。而以下的包主要用于数据分析,如果只想爬取基金数据,以上的包就已经足够了。数据分析包,pandas,numpy主要用于数组矩阵分析等数值计算;matpoltlib主要用于绘图,与matlab相关绘图方法和函数类似,学过或者用过matlab的朋友对此并不困难,各个数据分析的包处理方法都比较友好,易上手。
2.数据爬虫流程:
所谓,爬虫,即万千的网页,就像一张巨大的网,网中不同的节点存储着各种各样的数据,如新闻,基金,股票,游戏,图片等等。我们通过计算机的手段在指定的节点处快速获取我们想要的信息即爬虫。
爬虫的基本流程:模拟浏览器发送请求(获取网页代码)->通过正则表达式或其他方法提取有用数据->存放于数据库或者文件中
3.基金网站的选择:
明确了爬虫流程,我们还需要找到合适的基金网站,因为目前很多网站为了防止信息泄露,进行了反爬虫手段;比如建立浏览身份头user-agent的白名单,只有浏览时使用白名单范围内的user-agent才能有效访问。当然对此我们也可以通过伪装白名单的浏览器的手段来浏览网页;除此之外,反爬虫技术还有很多,如IP限制,JS脚本来防止爬虫等等。
当然,如果在爬虫的开始,我们就能找到具有目标信息且较友好的网站即是最好最方便的!
在此我们选择的基金网站是蛋卷基金网站:
网络页面如下:
首先我们随意选择一个基金,进入其净值所在的网页下:
进入后,点击ctrl+shift+c查看网页代码,并点击网络(net)属性,:
进行网页刷新,点击XHR:
在这里可以看到数据传送的网页,你可以尝试点击查看能否顺利打开,可以发现其能顺利打开,包含基金的净值,百分比,时间信息,且该网址有章可循,能为后期的爬虫处理带来方便:
在此我们便找到了想要爬虫的网站网址及编写方法:
https://danjuanapp.com/djapi/fund/nav/history/(基金代码)?size=30&page=1(页数)
4.数据爬虫:
有了数据爬取的网址编写方法,接下来我们就可以轻松的开始爬取网页数据了;
(1) 首先定义网页与发送访问请求的user-agent:
url="https://danjuanapp.com/djapi/fund/nav/history/"
guding="?size=30&page="
header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
在这里我们将该网址分成url和guding两端写,当我们想访问确定代码的网址时就可以通过以下方式来访问:
url+(基金代码)+guding
(2)接下来利用requests进行网页数据获取及正则化表达处理,代码如下:
url=url+daima+guding
print("正在爬取基金数据代号:",daima)
for i in range(1,31):
urll=url+str(i)
print(urll)
req=urllib.request.Request(url=urll,headers=header) #制定url,获取网页数据
response=urllib.request.urlopen(req)
html=response.read().decode("utf-8")
date=date+re.findall(r'"date":"(.*?)"',html) #正则化表达式,分别找到日期,净值,百分比数据
value=value+re.findall(r'"value":"(.*?)"',html)
percentage=percentage+re.findall(r'"percentage":"(.*?)"',html)
(3)剩下的就是数据存储了,这里将每个代码的基金放入每个创建的excel表中,以便我们后期进行分析使用。该段代码如下:
savepath="./"+daima+".xls"
name=daima
book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建workbook对象
sheet = book.add_sheet(name,cell_overwrite_ok=True) # 创建工作表
col=("日期","百分比增减","净值")
num= len(date)
for i in range(0,3):
sheet.write(0,i,col[i]) #列名
for i in range(0,num):
j=num-i
#print("爬取", date[j-1])
sheet.write(i+1,0,date[j-1])
sheet.write(i+1,1,percentage[j-1])
sheet.write(i+1,2,value[j-1])
book.save(savepath) # 保存数据表
print("爬取成功!")
(4)运行结果,通过以上步骤,我们将能对特定代号的基金进行数据提取,并存入excel表中,对应excel表的名称为该基金的代码,结果如下:
(5)将上述步骤结合起来,编写成函数,主要参数即为需要爬取的基金代码,返回爬取基金数据的excel表,函数代码如下:
'''基金数据爬取函数,主要参数输入基金代码,完成该基金数据获取'''
def jijinspider(daima="160002"):
#获取网页
#daima=int(daima)
url="https://danjuanapp.com/djapi/fund/nav/history/"#https://danjuanapp.com/djapi/fund/nav/history/004194?size=30&page=1
guding="?size=30&page="
header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
date=[]
value=[]
percentage=[]
url=url+daima+guding
print("正在爬取基金数据代号:",daima)
for i in range(1,31):
urll=url+str(i)
print(urll)
req=urllib.request.Request(url=urll,headers=header)
response=urllib.request.urlopen(req)
html=response.read().decode("utf-8")
date=date+re.findall(r'"date":"(.*?)"',html)
value=value+re.findall(r'"value":"(.*?)"',html)
percentage=percentage+re.findall(r'"percentage":"(.*?)"',html)
#print(date)
savepath="./"+daima+".xls"
name=daima
book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建workbook对象
sheet = book.add_sheet(name,cell_overwrite_ok=True) # 创建工作表
col=("日期","百分比增减","净值")
num= len(date)
for i in range(0,3):
sheet.write(0,i,col[i]) #列名
for i in range(0,num):
j=num-i
#print("爬取", date[j-1])
sheet.write(i+1,0,date[j-1])
sheet.write(i+1,1,percentage[j-1])
sheet.write(i+1,2,value[j-1])
book.save(savepath) # 保存数据表
print("爬取成功!")
2.基金数据月均值,周均值分析及净值绘图
根据基金数据的爬取,我们就可以对基金数据进行一定的分析和操作,目前,我对基金数据进行了月均值分析,周均值分析以及净值绘图,当然也还可以对百分比进行绘图或进行其他的数据分析,感兴趣的朋友可以接着这里继续进行数据分析,来使买入的基金对自己利益最大化。
(1)周均值分析,主要参数为excel表格,返回周均值列表
'''基金周均值分析,主要参数为excel表格,返回周均值列表'''
def weekavr(sheetpath):
jijinshu=pd.read_excel(sheetpath,skiprows=1,usecols=[1,2])
jijinshuju=np.array(jijinshu)
#jijinshuju=np.loadtxt(sheetname,skiprows=1,usecols=[1,2],encoding='utf-8')
#print(jijinshuju)
shujusize=jijinshuju.shape
#print(shujusize[0])
weekavre=[]
avrshu=0
for i in range(0,shujusize[0]):
if i%7!=6:
avrshu=avrshu+jijinshuju[i,1]
elif i==shujusize[0]-1 and i%7!=6:
j=i%7
avrshu = avrshu + jijinshuju[i, 1]
avrshu=avrshu/(j+1)
weekavre.append(avrshu)
avrshu=0
else:
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu /7
weekavre.append(avrshu)
avrshu = 0
#print(monthavr)
return weekavre
(2)月均值分析,主要参数为excel表格,返回周均值列表
'''月均值函数,这个函数主要返回基金每月均值,输入主要参数为基金存储表格路径'''
def monthavr(sheetpath):
jijinshu = pd.read_excel(sheetpath, skiprows=1, usecols=[1, 2])
jijinshuju = np.array(jijinshu)
# jijinshuju=np.loadtxt(sheetname,skiprows=1,usecols=[1,2],encoding='utf-8')
# print(jijinshuju)
shujusize = jijinshuju.shape
# print(shujusize[0])
monthavr = []
avrshu = 0
for i in range(0, shujusize[0]):
if i % 30 != 29:
avrshu = avrshu + jijinshuju[i, 1]
elif i == shujusize[0] - 1 and i % 30 != 29:
j = i % 30
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu / (j + 1)
monthavr.append(avrshu)
avrshu = 0
else:
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu / 30
monthavr.append(avrshu)
avrshu = 0
# print(monthavr)
return monthavr
(3)净值,周均值变化绘图,主要参数为:周均值矩阵,基金数据excel表格名称,在使用时注意代码中的路径为当前文件路径,如果路径不一样,可以修改代码路径或修改表格路径到当前文件路径:
'''这个函数主要用于画出基金几年时间段的数据变化趋势,主要参数为:周均值矩阵,基金数据excel表格'''
def jijinplot(sheetname,weekavr):
imagename=sheetname
sheetname="./"+sheetname
jijinshuju=pd.read_excel(sheetname)
jijinshuju_now=np.array(jijinshuju)
num=len(jijinshuju_now[:,1])
plt.plot(jijinshuju_now[:,0],jijinshuju_now[:,2])
plt.xticks(range(1,num,75), rotation=35)
plt.title(imagename)
plt.xlabel("time")
plt.ylabel("value")
num=len(weekavr)
for i in range(0,num):
xx=jijinshuju_now[7*i:7*i+7,0]
xx=np.array(xx)
#print(xx)
yy=[weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i]]
plt.plot(xx,yy)
#plt.xticks([])
plt.show()
效果如下图所示,净值变化折线与网站一致:
3.搜寻处于下降态势的基金
这一步,主要目的在于找到处于下降态势的基金,并输出。日常,大家都愿意将资金在基金或者股票处于低谷时进行投入,以期望在基金或股票上涨时牟取利益,这个函数主要作用就在于每次随机的搜寻处于下降态势的基金,并输出,供大家思考和选择。
这个函数除以下代码外,需要所有基金的代码表,这个表可以通过百度获取,将它整理为excel表格如下图所示,并不困难,这里不再赘述。
以下为实现代码与运行效果图:
'''下降基金代号获取函数,当前处于降低时期的基金,主要针对当前月均值,与周均值处于下降阶段,找到5个后停止,返回基金代号'''
def find_decend():
# 获取网页
url = "https://danjuanapp.com/djapi/fund/nav/history/" # https://danjuanapp.com/djapi/fund/nav/history/004194?size=30&page=1
guding = "?size=30&page="
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/86.0.4240.198 Safari/537.36"}
sheetpath = "./基金代码.xlsx"
jijinshu = pd.read_excel(sheetpath,dtype=str)
# jijinshu.info()
jijinshuju = np.array(jijinshu)
strr = jijinshuju[0, 0].zfill(6)
jijinshuju[0, 0] = strr
for i in range(0, 4178):
strr = jijinshuju[i, 0].zfill(6)
jijinshuju[i, 0] = strr
date = []
value = []
percentage = []
yx_daima=[]
daima=""
jiance=0
while (jiance<5) :
find_rand = np.random.randint(1000, 4179, (1, 100))
for j in range(0,100):
daima = jijinshuju[find_rand[0,j],0]
# print(daima)
url0 = url + daima + guding
print("正在随机验证基金代码:", jijinshuju[find_rand[0,j],0])
for i in range(1, 10):
urll = url0 + str(i)
#print(urll)
req = urllib.request.Request(url=urll, headers=header)
html = ""
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
#date = date + re.findall(r'"date":"(.*?)"', html)
value = value + re.findall(r'"value":"(.*?)"', html)
percentage = percentage + re.findall(r'"percentage":"(.*?)"', html)
# print(date)
#date=np.array(date)
#value=np.array(value,dtype=float)
#percentage=np.array(percentage)
shujusize = len(value)
if shujusize<100:
break
# print(value)
value_wk=[]
for float_i in value:
value_wk.append(float(float_i))
# print("shujusize:",shujusize)
# print(shujusize)
monthavr = []
avrshu = 0.00
for i in range(0, shujusize):
if i % 30 != 29:
avrshu = avrshu + value_wk[i]
elif i == shujusize - 1 and i % 30 != 29:
j = i % 30
avrshu = avrshu + value_wk[i]
avrshu = avrshu / (j + 1)
monthavr.append(avrshu)
avrshu = 0
else:
avrshu = avrshu + value_wk[i]
avrshu = avrshu / 30
monthavr.append(avrshu)
avrshu = 0
weekavre = []
avrshu = 0
for i in range(0, shujusize):
if i % 7 != 6:
avrshu = avrshu + value_wk[i]
elif i == shujusize - 1 and i % 7 != 6:
j = i % 7
avrshu = avrshu + value_wk[i]
avrshu = avrshu / (j + 1)
weekavre.append(avrshu)
#print(avrshu)
avrshu = 0
else:
avrshu = avrshu + value_wk[i]
avrshu = avrshu / 7
#print(avrshu)
weekavre.append(avrshu)
avrshu = 0
# weekavre=np.array(weekavre)
# monthavr=np.array(monthavr)
week_size=len(weekavre)
month_size=len(monthavr)
# print(weekavre)
# print(week_size)
percd_w=(weekavre[week_size-2]-weekavre[week_size-1])/weekavre[week_size-2]
percd_m=(monthavr[month_size-2]-monthavr[month_size-1])/monthavr[month_size-1]
if percd_m>0.2 and percd_w>0 and monthavr[month_size-2]>3:
yx_daima.append(jijinshuju[find_rand[0,j],0])
jiance = jiance + 1
print("找到第",jiance,"个基金代码为",jijinshuju[find_rand[0,j],0],
"的",jijinshuju[find_rand[0,j],1],"处于下降态势,月下降态势为:",percd_m,"周下降态势为:",percd_w)
在使用时,只需调用该函数即可,运行效果如下:
所有函数代码
from bs4 import BeautifulSoup #进行网页解析获取数据
import re #正则表达式,进行文字匹配
import urllib.request,urllib.error #制定URL。获取网页数据
import xlwt #进行excel操作
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import random
import xlrd
'''基金数据爬取函数,主要参数输入基金代码,完成该基金数据获取'''
def jijinspider(daima="160002"):
#获取网页
#daima=int(daima)
url="https://danjuanapp.com/djapi/fund/nav/history/"#https://danjuanapp.com/djapi/fund/nav/history/004194?size=30&page=1
guding="?size=30&page="
header={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36"}
date=[]
value=[]
percentage=[]
url=url+daima+guding
print("正在爬取基金数据代号:",daima)
for i in range(1,31):
urll=url+str(i)
print(urll)
req=urllib.request.Request(url=urll,headers=header)
response=urllib.request.urlopen(req)
html=response.read().decode("utf-8")
date=date+re.findall(r'"date":"(.*?)"',html)
value=value+re.findall(r'"value":"(.*?)"',html)
percentage=percentage+re.findall(r'"percentage":"(.*?)"',html)
#print(date)
savepath="./"+daima+".xls"
name=daima
book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建workbook对象
sheet = book.add_sheet(name,cell_overwrite_ok=True) # 创建工作表
col=("日期","百分比增减","净值")
num= len(date)
for i in range(0,3):
sheet.write(0,i,col[i]) #列名
for i in range(0,num):
j=num-i
#print("爬取", date[j-1])
sheet.write(i+1,0,date[j-1])
sheet.write(i+1,1,percentage[j-1])
sheet.write(i+1,2,value[j-1])
book.save(savepath) # 保存数据表
print("爬取成功!")
'''基金周均值分析,主要参数为excel表格,返回周均值列表'''
def weekavr(sheetpath):
jijinshu=pd.read_excel(sheetpath,skiprows=1,usecols=[1,2])
jijinshuju=np.array(jijinshu)
#jijinshuju=np.loadtxt(sheetname,skiprows=1,usecols=[1,2],encoding='utf-8')
#print(jijinshuju)
shujusize=jijinshuju.shape
#print(shujusize[0])
weekavre=[]
avrshu=0
for i in range(0,shujusize[0]):
if i%7!=6:
avrshu=avrshu+jijinshuju[i,1]
elif i==shujusize[0]-1 and i%7!=6:
j=i%7
avrshu = avrshu + jijinshuju[i, 1]
avrshu=avrshu/(j+1)
weekavre.append(avrshu)
avrshu=0
else:
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu /7
weekavre.append(avrshu)
avrshu = 0
#print(monthavr)
return weekavre
'''这个函数主要用于画出基金几年时间段的数据变化趋势,主要参数为:周均值矩阵,基金数据excel表格'''
def jijinplot(sheetname,weekavr):
imagename=sheetname
sheetname="./"+sheetname
jijinshuju=pd.read_excel(sheetname)
jijinshuju_now=np.array(jijinshuju)
num=len(jijinshuju_now[:,1])
plt.plot(jijinshuju_now[:,0],jijinshuju_now[:,2])
plt.xticks(range(1,num,75), rotation=35)
plt.title(imagename)
plt.xlabel("time")
plt.ylabel("value")
num=len(weekavr)
for i in range(0,num):
xx=jijinshuju_now[7*i:7*i+7,0]
xx=np.array(xx)
#print(xx)
yy=[weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i],weekavr[i]]
plt.plot(xx,yy)
#plt.xticks([])
plt.show()
'''月均值函数,这个函数主要返回基金每月均值,输入主要参数为基金存储表格路径'''
def monthavr(sheetpath):
jijinshu = pd.read_excel(sheetpath, skiprows=1, usecols=[1, 2])
jijinshuju = np.array(jijinshu)
# jijinshuju=np.loadtxt(sheetname,skiprows=1,usecols=[1,2],encoding='utf-8')
# print(jijinshuju)
shujusize = jijinshuju.shape
# print(shujusize[0])
monthavr = []
avrshu = 0
for i in range(0, shujusize[0]):
if i % 30 != 29:
avrshu = avrshu + jijinshuju[i, 1]
elif i == shujusize[0] - 1 and i % 30 != 29:
j = i % 30
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu / (j + 1)
monthavr.append(avrshu)
avrshu = 0
else:
avrshu = avrshu + jijinshuju[i, 1]
avrshu = avrshu / 30
monthavr.append(avrshu)
avrshu = 0
# print(monthavr)
return monthavr
# sheetname="004194.xls"
# weekshuju=monthavr(sheetname)
# print(weekshuju)
# jijinspider("004194")
# sheetname="004194.xls"
# weekshuju=weekavr(sheetname)
# #print(weekshuju)
# jijinplot("004194.xls",weekshuju)
'''月周期基金代理分析,这个函数主要对基金数据每月数据变化进行分析,以求找到买入与卖出基金的合适时间'''
#def T_jijin(sheetname):
'''下降基金代号获取函数,当前处于降低时期的基金,主要针对当前月均值,与周均值处于下降阶段,找到5个后停止,返回基金代号'''
def find_decend():
# 获取网页
url = "https://danjuanapp.com/djapi/fund/nav/history/" # https://danjuanapp.com/djapi/fund/nav/history/004194?size=30&page=1
guding = "?size=30&page="
header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/86.0.4240.198 Safari/537.36"}
sheetpath = "./基金代码.xlsx"
jijinshu = pd.read_excel(sheetpath,dtype=str)
# jijinshu.info()
jijinshuju = np.array(jijinshu)
strr = jijinshuju[0, 0].zfill(6)
jijinshuju[0, 0] = strr
for i in range(0, 4178):
strr = jijinshuju[i, 0].zfill(6)
jijinshuju[i, 0] = strr
date = []
value = []
percentage = []
yx_daima=[]
daima=""
jiance=0
while (jiance<5) :
find_rand = np.random.randint(1000, 4179, (1, 100))
for j in range(0,100):
daima = jijinshuju[find_rand[0,j],0]
# print(daima)
url0 = url + daima + guding
print("正在随机验证基金代码:", jijinshuju[find_rand[0,j],0])
for i in range(1, 10):
urll = url0 + str(i)
#print(urll)
req = urllib.request.Request(url=urll, headers=header)
html = ""
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
#date = date + re.findall(r'"date":"(.*?)"', html)
value = value + re.findall(r'"value":"(.*?)"', html)
percentage = percentage + re.findall(r'"percentage":"(.*?)"', html)
# print(date)
#date=np.array(date)
#value=np.array(value,dtype=float)
#percentage=np.array(percentage)
shujusize = len(value)
if shujusize<100:
break
# print(value)
value_wk=[]
for float_i in value:
value_wk.append(float(float_i))
# print("shujusize:",shujusize)
# print(shujusize)
monthavr = []
avrshu = 0.00
for i in range(0, shujusize):
if i % 30 != 29:
avrshu = avrshu + value_wk[i]
elif i == shujusize - 1 and i % 30 != 29:
j = i % 30
avrshu = avrshu + value_wk[i]
avrshu = avrshu / (j + 1)
monthavr.append(avrshu)
avrshu = 0
else:
avrshu = avrshu + value_wk[i]
avrshu = avrshu / 30
monthavr.append(avrshu)
avrshu = 0
weekavre = []
avrshu = 0
for i in range(0, shujusize):
if i % 7 != 6:
avrshu = avrshu + value_wk[i]
elif i == shujusize - 1 and i % 7 != 6:
j = i % 7
avrshu = avrshu + value_wk[i]
avrshu = avrshu / (j + 1)
weekavre.append(avrshu)
#print(avrshu)
avrshu = 0
else:
avrshu = avrshu + value_wk[i]
avrshu = avrshu / 7
#print(avrshu)
weekavre.append(avrshu)
avrshu = 0
# weekavre=np.array(weekavre)
# monthavr=np.array(monthavr)
week_size=len(weekavre)
month_size=len(monthavr)
# print(weekavre)
# print(week_size)
percd_w=(weekavre[week_size-2]-weekavre[week_size-1])/weekavre[week_size-2]
percd_m=(monthavr[month_size-2]-monthavr[month_size-1])/monthavr[month_size-1]
if percd_m>0.1 and percd_w>0 and monthavr[month_size-2]>3:
yx_daima.append(jijinshuju[find_rand[0,j],0])
jiance = jiance + 1
print("找到第",jiance,"个基金代码为",jijinshuju[find_rand[0,j],0],
"的",jijinshuju[find_rand[0,j],1],"处于下降态势,月下降态势为:",percd_m,"周下降态势为:",percd_w)