数据库接口(Python爬取天天基金网基金数据(一))

数据库接口(Python爬取天天基金网基金数据(一))
Python爬取天天基金网基金数据(一)

最近做了一个基金数据分析工具,用于自动获取当天所有基金净值、增长率、实时估值、历史净值等明细数据,并进行数据分析,计划分多期展开来分享,覆盖Python的爬虫、数据库等相关知识点。

首先从数据获取开始,本次案例数据来源为天天基金网所有基金数据,并固化至数据库和excel文件。

环境准备

pip install requests      #爬虫接口库pip install sqlalchemy  #mysql数据库接口库

数据来源url

天天基金网基金数据有单独的API接口,只需要一个url请求,即可获取当天某一特定类型的所有基金数据。按基金类型分股票、债券、混合、偏股、指数等接口,具体如下:

url_list = [ # 股票、债券、混合、偏股、指数、QDII       'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=gp&pi=1&pn=5',       'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=zq&pi=1&pn=5',        'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=hh&pi=1&pn=5',        'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=pg&pi=1&pn=5',        'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=zs&pi=1&pn=5',        'https://fundapi.eastmoney.com/fundtradenew.aspx?ft=qdii&pi=1&pn=5'            ]

数据获取

以股票型为例url为:

数据库接口(Python爬取天天基金网基金数据(一))

https://fundapi.eastmoney.com/fundtradenew.aspx?ft=gp&pi=1&pn=5

其中pi=1表示从第1页开始,pn=65536每页获取记录数,在浏览器请求,返回结果为json格式数据,:

数据格式

如图所示,股票型基金共有1295只,当前页为第一页,每页数量为5,共有259页,因此可在url中直接修改为pn=65536,则一次性获取全部股票基金数据。

Python请求:

resp = requests.get(url)

数据解析

  • 数据提取

上图中,基金明细数据为列表格式,每只基金以|隔开,话不多说,直接上代码,数据处理如下:

 # 取请求返回结果部分     html_str = resp.text    # 返回结果中取出json部分    datas = html_str[html_str.find('{'):html_str.find('}')+1]    # 给json各字段名添加双引号    datas = datas.replace('datas', '\"datas\"')    datas = datas.replace('allRecords', '\"allRecords\"')    datas = datas.replace('pageIndex', '\"pageIndex\"')    datas = datas.replace('pageNum', '\"pageNum\"')    datas = datas.replace('allPages', '\"allPages\"')    datas = datas.replace('allNum', '\"allNum\"') # 全部基金数    datas = datas.replace('gpNum', '\"gpNum\"')  # 股票型基金数量    datas = datas.replace('hhNum', '\"hhNum\"')  # 混合型基金数量    datas = datas.replace('zqNum', '\"zqNum\"')  # 债券型基金数量    datas = datas.replace('zsNum', '\"zsNum\"')  # 指数型基金数量    datas = datas.replace('bbNum', '\"bbNum\"')  # 保本型基金数量    datas = datas.replace('qdiiNum', '\"qdiiNum\"')# QDII型基金数量        datas = datas.replace('etfNum', '\"etfNum\"') # ETF型基金数量    datas = datas.replace('lofNum', '\"lofNum\"') # LOF型基金数量    datas = datas.replace('fofNum', '\"fofNum\"') # FOF型基金数量    #转换成json格式数据    jsonBody = json.loads(datas)    #取”datas“字段数据    jsonDatas = jsonBody['datas']
  • 封装成pandas的Dataframe格式

为了数据持久性,一般需要把数据写入数据库或文件保存,这里分别以mysql及excel为例,将上述提取的json格式数据封装成pandas的Dataframe格式以方便写入mysql或excel数据库,json封装成Dataframe格式、异常数据处理如下:

    df = pd.DataFrame(columns=('code','name','type','fund_date','net_value',                               'ratedate1', 'rateweek1', 'ratemonth1', 'ratemonth3', 'ratemonth6',                                'rateyear1', 'rateyear2', 'rateyear3','rate_this_year','rate_from_fund'))    for i in range(len(jsonDatas)):        # 用逗号分隔,空值用0补充,最后将每行数据加入到dataframe中        df.loc[i] = [0 if x == '' else x for x in jsonDatas[i].split('|')[0:15]]    #加上今天作为采样日期     df['partstart'] = cur_datetime     # 增长率中含有逗号的表示法需要把逗号去掉,如增长率:1,043.56转换成1043.6才能写进数据库     df['rate_from_fund'] = df['rate_from_fund'].map(lambda str_val: str_val.replace(',', '') if ',' in str_val else str_val)    # 剔除当天净值、基金日期、累计净值为0的记录,~表示取反操作    df=df[~df['fund_date'].isin([0])]    # 只取程序执行当天有净值的数据     df=df[df['fund_date'] == cur_date]

数据持久化

数据持久化就是将获取的数据固化到数据库或excel中,上一步骤中Dataframe格式的数据可直接写入到mysql数据库或excel文件。

  • 保存到mysql数据库

用到sqlalchemy库,可通过pip install sqlalchemy语句安装。首先需要在数据库中建立表结构,表结构如下:

create table fund_jingzhi(        code                varchar(10) not null COMMENT  '基金代码',        name                varchar(200)  not null COMMENT  '基金名',        type                varchar(200) COMMENT  '基金类型',        fund_date            date  not null COMMENT  '基金日期',        net_value           float  not null COMMENT  '单位净值',        ratedate1          float COMMENT  '日增长率',        rateweek1          float COMMENT  '近1周',        ratemonth1         float COMMENT  '近1月',        ratemonth3         float COMMENT  '近3月',        ratemonth6         float COMMENT  '近6月',        rateyear1         float COMMENT  '近1年',        rateyear2         float COMMENT  '近2年',        rateyear3         float COMMENT  '近3年',        rate_this_year         float COMMENT  '今年来',        rate_from_fund        float COMMENT  '成立来',        partstart          datetime not null COMMENT  '采集日期',        primary key(code,fund_date)    )ENGINE=InnoDB DEFAULT CHARSET=utf8;

接着写入数据库比较简单,两行代码即可:

#建立与mysql连接 db_connect = create_engine('mysql+pymysql://用户名:密码@IP:3306/dbname?charset=utf8') #将整个df Dataframe变量的所有记录一次写入fund.fund_all表中# index = False 表示dataframe中的index值不会写入数据库表res = pd.io.sql.to_sql(df,'fund_jingzhi', db_connect, schema='fund', if_exists='append',index = False,dtype=dtypedict_fund_jingzhi)

其中dtypedict_fund_jingzhi为dataframe中的列与表结构字段格式保持一致,dtypedict_fund_jingzhi定义如下:

dtypedict_fund_jingzhi = {       'code':NVARCHAR(length=10),       'name':NVARCHAR(length=200),       'fund_date':Date(),       'net_value':Float(),       'ratedate1':Float(),       'rateweek1':Float(),       'ratemonth1':Float(),       'ratemonth3':Float(),       'ratemonth6':Float(),       'rateyear1':Float(),       'rateyear2':Float(),       'rateyear3':Float(),       'rate_this_year':Float(),       'rate_from_fund':Float(),       'partstart':DateTime()    }
  • 保存到excel文件
  • 保存到文件也很简单,函数如下:

    def w2excel(df,file):    writer = pd.ExcelWriter(file)    df.to_excel(writer,'基金明细')    writer.save()

    后记


    文章开头直接给出了天天基金网的基金净值数据API接口,怎么获取这个API呢?同时部分数据比如基金历史净值数据、实时动态估值数据,并不能通过网页分析直接获取数据接口,或者根据接口不能简单直接获取数据,又要如何解决呢?这部分将在第二篇展开分析。


    关注本公众号“融智圈”并回复“基金”可获取源码。

    文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

    相关阅读

    最新文章

    热门文章

    本栏目文章