1
最近公募基金扎堆发四季度报告,截至今天,所有公募基金四季报已经全部公布完了。基金的季度报告里可以查看基金的各种信息,如果想购买一个基金,最好的办法可能是先看看他过去几年的报告,了解一下投资风格。
以A股首个千亿基金经理张坤为例,来看看他的明星产品易方达中小盘,在今年四季度报告里都写了些什么
产品概况
产品表现,过去一年84%的超高收益
基金经理的投资逻辑说明和对未来的展望:
2
接下来我们用python获取基金的报告,先给一个使用说明,源码和逻辑见后文
我用python定义了getpdfurl和getFundReportpdf两个函数:
getpdfurl包括三个输入:基金代码,基金公告的起止时间,举个例子,比如易方达中小盘,百度看到他的基金代码是110011
我们来获取他的四季报,起止时间设定为20201231到20210131,代码如下
# 易方达中小盘
codes = '110011'
sdate = '20201231'
edate = '20210131'
allpdf = getpdfurl(codes,sdate,edate)
运行结果如下
返回的是获取到的基金名称还有这段时间里已经发布的所有报告,我们把时间拉长,看看他过去5年发的报告
# 易方达中小盘
codes = '110011'
sdate = '20151231'
edate = '20210131'
allpdf = getpdfurl(codes,sdate,edate)
这个就有点多了,贴一部分。
接下里是第二步,使用刚才获取到的列表下载pdf,调用getFundReportpdf函数即可,getFundReportpdf有两个输入,第一个输入是刚才获取到的allpdf这个dataframe,第二个是pdf保存的路径,比如我存在我电脑E盘的一个文件夹下,调用如下
fpath = 'E:\\基金公告\\pdf\\'
getFundReportpdf(allpdf,fpath)
运行完可以看到文件夹里已经自动保存了这些pdf
使用是非常方便的,有一个python,对任何一个你想了解的基金,找到他的基金代码,你就可以批量获取到他的公告。下面是源码的原理和获取方式。
3
获取源码文件请直接在后台回复“基金季报”
这里我是从巨潮资讯上爬取的,打开切到基金这一栏,选择年报、中报、季报,可以看到,下面已经列了非常多基金的报告了
接下来是,如何获取给定基金代码的报告,上图右边,可以输入代码标题简称,就是这里了,我们输入110011,会出现一个提示栏,正是我们查询的基金名称,起始日期这个先不用改。
点击出现的提示栏,返回的是所有这段时间内的报告列表
随便点开一个就是我们需要的pdf了
接下来说明如何用python完成以上的这些步骤,在前面输入110011的时候,如果我们打开了浏览器的开发者工具(F12),转到NetWork这一栏,再点击跳转,选择XHR,可以看到,返回了一个query
点击query,再选择preview,可以看到,就是我们需要的数据
然后我们看看他的header
Gernel里可以看到对应的网址是http://www.cninfo.com.cn/new/hisAnnouncement/query,request method是post
往下拉,看看request header 和form data,这些是获取数据需要的header和参数
Form Data里是传入需要的数据,主要关注两个位置,seDate是起止时间,stock是传入的代码,110011是我们刚刚传入的,jjjl100000041是它自动生成的,只要能找到每个基金代码对应的自动生成的代码,就可以得到stock的参数,就可以爬下来了。
而这个对应的关系,在前一个页面里,有个fund_stock的json,可以看到,把这个数据获取下来就可以了。
源码如下
import pandas as pd
import numpy as np
import os
import urllib
import requests
from fake_useragent import UserAgent
import json
import time
def getpdfurl(codes,sdate,edate):
sdate = pd.Timestamp(sdate).strftime('%Y-%m-%d')
edate = pd.Timestamp(edate).strftime('%Y-%m-%d')
ords = a[codes]
stocks = codes + ',' + ords
params = {
'pageNum': '1',
'pageSize': '30',
'column': 'fund',
'tabName': 'fulltext',
'plate':'' ,
'stock': stocks,
'searchkey':'' ,
'secid':'' ,
'category': 'category_ndbg_jjgg;category_bndbg_jjgg;category_jdbg_jjgg',
'trade':'' ,
'seDate': '{}~{}'.format(sdate,edate),
'sortName': '',
'sortType': '',
'isHLtitle': 'true'}
url = 'http://www.cninfo.com.cn/new/hisAnnouncement/query'
headers = {"User-Agent": UserAgent(verify_ssl=False).random}
response_comment = requests.post(url,params = params,headers = headers )
res = json.loads(response_comment.text)
n = len(res['announcements'])
allpdf = []
for k in range(n):
allpdf.append(pd.DataFrame.from_dict(res['announcements'][k],orient='index').T)
allpdf = pd.concat(allpdf,axis = 0).reset_index(drop = True)
allpdf = allpdf[['secName','announcementTitle','adjunctUrl']]
return allpdf
三个输入:基金代码,开始时间,结束时间
接下来是获取pdf,这个就很容易了,刚刚获取到的数据里有网址,直接用request.get获取,用open函数保存就可以了
def getFundReportpdf(allpdf,fpath):
headers = {"User-Agent": UserAgent(verify_ssl=False).random}
for k in range(allpdf.shape[0]):
url = allpdf.adjunctUrl[k]
urls = 'http://static.cninfo.com.cn/{}#navpanes=0&toolbar=0&statusbar=0&pagemode=thumbs&page=1'.format(url)
fname =allpdf.announcementTitle[k]
r = requests.get(urls, timeout = 300,headers = headers)
with open (fpath + '{}.pdf'.format(fname),'wb') as f:
f.write(r.content)
f.close()
time.sleep(2)
以上是源码,这里省去了获取对应关系的部分,需要请查看源码文件。