欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

TuShare中源码分析(获取个股数据和基本面宏观数据)

程序员文章站 2022-04-02 11:18:08
TuShare源码的入口是__init__.py文件,我们从这个文件开始分析。入口# -*- coding:utf-8 -*- import codecsimport os__version__ = codecs.open(os.path.join(os.path.dirname(__file__), 'VERSION.txt')).read()__author__ = 'Jimmy Liu'上面的代码是TuShare的版本和作者"""for trading data"""fro...



今天,我们来分析下TuShare中的源码,TuShare源码的入口是__init__.py文件,我们从这个文件开始分析,找到获取个股历史交易记录并进行分析。


1、入口

# -*- coding:utf-8 -*- import codecs import os

__version__ = codecs.open(os.path.join(os.path.dirname(__file__), 'VERSION.txt')).read() __author__ = 'Jimmy Liu' 

上面的代码是TuShare的版本和作者

2、个股交易数据

""" for trading data """ from tushare.stock.trading import (get_hist_data, get_tick_data, get_today_all, get_realtime_quotes, get_h_data, get_today_ticks, get_index, get_hists, get_k_data, get_day_all, get_sina_dd, bar, tick, get_markets, quotes, get_instrument, reset_instrument) 

上面代码说明TuShare的16个交易数据API是从stock下的trading模块打包出来的。
我们打开源码stock目录下的trading.py文件,先分析trading.py的依赖项

from __future__ import division import time import json import lxml.html from lxml import etree import pandas as pd import numpy as np import datetime from tushare.stock import cons as ct	# 引入cons.py,包含股票相关常量定义 import re from pandas.compat import StringIO from tushare.util import dateu as du	# 引入dateu.py,日期、交易日历的处理 from tushare.util.formula import MA # 引入formula.py,包含股票常用指标 import os from tushare.util.conns import get_apis, close_apis		# 引入conns.py,连接爬取外部数据的API from tushare.stock.fundamental import get_stock_basics	# 引入fundamental.py,包含基本面数据接口 try: from urllib.request import urlopen, Request
except ImportError: from urllib2 import urlopen, Request 

我们可以看出,引入了5个模块:cons.py包含股票相关常量定义,dateu.py包含对日期、交易日历的处理,formula.py包含股票常用指标,conns.py包含连接爬取外部数据的API,fundamental.py包含基本面数据接口 。

2.1、API:获取凤凰财经个股历史交易记录

 def get_hist_data(code=None, start=None, end=None, ktype='D', retry_count=3, pause=0.001): 

代码中有获取个股历史交易记录API的详细说明:

 """
        获取个股历史交易记录
    Parameters ------ code:string
                  股票代码 e.g. 600848 start:string
                  开始日期 format:YYYY-MM-DD 为空时取到API所提供的最早日期数据
      end:string
                  结束日期 format:YYYY-MM-DD 为空时取到最近一个交易日数据
      ktype:string
                  数据类型,D=日k线 W=M=5=5分钟 15=15分钟 30=30分钟 60=60分钟,默认为D retry_count : int, 默认 3 如遇网络等问题重复执行的次数 
      pause : int, 默认 0 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题 return ------- DataFrame
          属性:日期 ,开盘价, 最高价, 收盘价, 最低价, 成交量, 价格变动 ,涨跌幅,5日均价,10日均价,20日均价,5日均量,10日均量,20日均量,换手率 """ 
参数 缺省值 说明
ktype ‘D’ 表示数据类型缺省是日线
retry_count 3 表示爬取外部数据请求时最多尝试3次
pause 0.001 表示多次尝试爬取请求过程中暂停0.001秒
 symbol = ct._code_to_symbol(code) 

我们在cons.py中找到_code_to_symbol

def _code_to_symbol(code): '''
        生成symbol代码标志 ''' if code in INDEX_LABELS: return INDEX_LIST[code] elif code[:3] == 'gb_': return code else: if len(code) != 6 : # 如果输入的不是一个6位数的股票代码 return code		# 直接返回代码 else: return 'sh%s'%code if code[:1] in ['5', '6', '9'] or code[:2] in ['11', '13'] else 'sz%s'%code	
            # 输入的是一个6位数的股票代码,代码前1位是569,或者前2位是1113,是上证股票代码,
            # 否则是深证股票代码,返回带市场的股票代码 

_code_to_symbol主要是对输入的股票代码进行判断,然后格式化成股票代码的标准格式,例如:sh600000

代码 cons.py中对应内容 说明
return INDEX_LIST[code] INDEX_LABELS = [‘sh’, ‘sz’, ‘hs300’, ‘sz50’, ‘cyb’, ‘zxb’, ‘zx300’, ‘zh500’] \n INDEX_LIST = {‘sh’: ‘sh000001’, ‘sz’: ‘sz399001’, ‘hs300’: ‘sh000300’,‘sz50’: ‘sh000016’, ‘zxb’: ‘sz399005’, ‘cyb’: ‘sz399006’, ‘zx300’: ‘sz399008’, ‘zh500’:‘sh000905’} 根据缩写指标代码返回指标对应的完整指标代码
 url = '' if ktype.upper() in ct.K_LABELS: url = ct.DAY_PRICE_URL%(ct.P_TYPE['http'], ct.DOMAINS['ifeng'], ct.K_TYPE[ktype.upper()], symbol) # 拼装日线对应凤凰网数据请求API的url 
代码 cons.py中对应内容 说明
ct.K_LABELS K_LABELS = [‘D’, ‘W’, ‘M’] 数据类型,D:日线,W:周线,M:月线
ct.DAY_PRICE_URL DAY_PRICE_URL = ‘%sapi.finance.%s/%s/?code=%s&type=last’ 凤凰网获取日线的URL
ct.P_TYPE[‘http’]- P_TYPE = {‘http’: ‘http://’, ‘ftp’: ‘ftp://’}- http请求类型
ct.DOMAINS[‘ifeng’]- ‘ifeng’: ‘ifeng.com’- 数据来源凤凰
ct.K_TYPE K_TYPE = {‘D’: ‘akdaily’, ‘W’: ‘akweekly’, ‘M’: ‘akmonthly’} 数据类型和凤凰网对应的数据类型,D:日线,W:周线,M:月线
 elif ktype in ct.K_MIN_LABELS: url = ct.DAY_PRICE_MIN_URL%(ct.P_TYPE['http'], ct.DOMAINS['ifeng'], symbol, ktype) # 拼装分钟线对应凤凰网数据请求API的url else: raise TypeError('ktype input error.') 
代码 cons.py中对应内容 说明
ct.K_MIN_LABELS K_MIN_LABELS = [‘5’, ‘15’, ‘30’, ‘60’] 分钟线:5分钟线、15分钟线、30分钟线、小时线
ct.DAY_PRICE_MIN_URL DAY_PRICE_MIN_URL = ‘%sapi.finance.%s/akmin?scode=%s&type=%s’ 凤凰网获取分钟线的URL
ct.P_TYPE[‘http’]- P_TYPE = {‘http’: ‘http://’, ‘ftp’: ‘ftp://’}- http请求类型
ct.DOMAINS[‘ifeng’]- ‘ifeng’: ‘ifeng.com’- 数据来源凤凰财经
ct.K_TYPE K_TYPE = {‘D’: ‘akdaily’, ‘W’: ‘akweekly’, ‘M’: ‘akmonthly’} 数据类型,D:日线,W:周线,M:月线

我们在这里给出两上请求凤凰网数据的示例,
a、请求上海证券交易所600000浦发银行的日线数据对应的URL:

http://api.finance.ifeng.com/akdaily/?code=sh600000&type=last 

TuShare中源码分析(获取个股数据和基本面宏观数据)

b、请求上海证券交易所600000浦发银行的周线数据对应的URL:

http://api.finance.ifeng.com/akweekly/?code=sh600000&type=last 

TuShare中源码分析(获取个股数据和基本面宏观数据)
c、请求一个不个不存在的股票数据,返回空数据

http://api.finance.ifeng.com/akdaily/?code=sh69999&type=last 

返回内容为13个字节的空记录内容

{"record":{}} 

在这里,我们展开说一下,我们可以通过凤凰财经的页面来分析爬取数据的URL,我们以浦发银行sh600000为例,打开浦发银行的行情页面:

http://finance.ifeng.com/app/hq/stock/sh600000/ 

TuShare中源码分析(获取个股数据和基本面宏观数据)
按F12打开开发者工具,切换到Network页面,在行情页面点击日k、周k、月k、15分、30分等进行数据类型切换,在Network页面查看请求的变化,分析对应的请求,我们就可以找到数据请求的API。
TuShare中源码分析(获取个股数据和基本面宏观数据)

 for _ in range(retry_count): # 尝试爬取retry_count次
        time.sleep(pause) # 休眠pause秒 try: request = Request(url) # 请求打开URL页面
            lines = urlopen(request, timeout = 10).read() # 保存返回页面内容到lines中 if len(lines) < 15: # 根据返回内容的长度来判断是否有数据,空数据返回{"record":{}} return None
        except Exception as e: print(e) # 如果出现异常,打印异常信息 else: 

凤凰财经返回的数据是JSON格式,下面代码是对爬取数据的处理

 js = json.loads(lines.decode('utf-8') if ct.PY3 else lines) cols = [] if (code in ct.INDEX_LABELS) & (ktype.upper() in ct.K_LABELS): cols = ct.INX_DAY_PRICE_COLUMNS else: cols = ct.DAY_PRICE_COLUMNS if len(js['record'][0]) == 14: # 如果第列是14个元素,代表是指标数据
                cols = ct.INX_DAY_PRICE_COLUMNS # 根据行记录数据创建DataFrame对象
            df = pd.DataFrame(js['record'], columns=cols) if ktype.upper() in ['D', 'W', 'M']: df = df.applymap(lambda x: x.replace(u',', u'')) df[df==''] = 0 for col in cols[1:]: df[col] = df[col].astype(float) # 进行类型转换 if start is not None: df = df[df.date >= start] # 保留开始时间之后的数据 if end is not None: df = df[df.date <= end] # 保留结束时间之前的数据 if (code in ct.INDEX_LABELS) & (ktype in ct.K_MIN_LABELS): df = df.drop('turnover', axis=1) df = df.set_index('date') # 按date字段设置索引
            df = df.sort_index(ascending = False) # 按索引进行排序 return df
    raise IOError(ct.NETWORK_URL_ERROR_MSG) 
代码 cons.py中对应内容 说明
ct.INDEX_LABELS INDEX_LABELS = [‘sh’, ‘sz’, ‘hs300’, ‘sz50’, ‘cyb’, ‘zxb’, ‘zx300’, ‘zh500’] 凤凰财经对应的指数代码
ct.INX_DAY_PRICE_COLUMNS INX_DAY_PRICE_COLUMNS = [‘date’, ‘open’, ‘high’, ‘close’, ‘low’, ‘volume’, ‘price_change’, ‘p_change’,‘ma5’, ‘ma10’, ‘ma20’, ‘v_ma5’, ‘v_ma10’, ‘v_ma20’] 指标日线数据每列的元素
ct.DAY_PRICE_COLUMNS DAY_PRICE_COLUMNS = [‘date’, ‘open’, ‘high’, ‘close’, ‘low’, ‘volume’, ‘price_change’, ‘p_change’,‘ma5’, ‘ma10’, ‘ma20’, ‘v_ma5’, ‘v_ma10’, ‘v_ma20’, ‘turnover’] 股票日线数据每列的元素

2.2、API:获取分笔数据

def get_tick_data(code=None, date=None, retry_count=3, pause=0.001, src='sn'): 

代码中有获取分笔数据API的详细说明:

 """
        获取分笔数据
    Parameters ------ code:string
                  股票代码 e.g. 600848 date:string
                  日期 format: YYYY-MM-DD retry_count : int, 默认 3 如遇网络等问题重复执行的次数
        pause : int, 默认 0 重复请求数据过程中暂停的秒数,防止请求间隔时间太短出现的问题
        src : 数据源选择,可输入sn(新浪)、tt(腾讯)、nt(网易),默认sn return ------- DataFrame 当日所有股票交易数据(DataFrame) 属性:成交时间、成交价格、价格变动,成交手、成交金额(),买卖类型 """ 
参数 缺省值 说明
retry_count 3 表示爬取外部数据请求时最多尝试3次
pause 0.001 表示多次尝试爬取请求过程中暂停0.001秒
src ‘sn’ 表示数据源选择新浪
 if (src.strip() not in ct.TICK_SRCS): print(ct.TICK_SRC_ERROR) return None				# 非法数据源,返回None
    symbol = ct._code_to_symbol(code) # 根据code获取symbol代码
    symbol_dgt = ct._code_to_symbol_dgt(code) # 根据code获取symbol_dgt代码
    datestr = date.replace('-', '') # 日期YYYY-MM-DD格式调整至YYYYMMDD格式 
代码 cons.py中对应内容 说明
ct.TICK_SRCS TICK_SRCS = [‘sn’, ‘tt’, ‘nt’] 分笔数据源,sn(新浪)、tt(腾讯)、nt(网易)
ct.INX_DAY_PRICE_COLUMNS INX_DAY_PRICE_COLUMNS = [‘date’, ‘open’, ‘high’, ‘close’, ‘low’, ‘volume’, ‘price_change’, ‘p_change’,‘ma5’, ‘ma10’, ‘ma20’, ‘v_ma5’, ‘v_ma10’, ‘v_ma20’] 指标日线数据每列的元素
ct.DAY_PRICE_COLUMNS DAY_PRICE_COLUMNS = [‘date’, ‘open’, ‘high’, ‘close’, ‘low’, ‘volume’, ‘price_change’, ‘p_change’,‘ma5’, ‘ma10’, ‘ma20’, ‘v_ma5’, ‘v_ma10’, ‘v_ma20’, ‘turnover’] 股票日线数据每列的元素
 url = { ct.TICK_SRCS[0] : ct.TICK_PRICE_URL % (ct.P_TYPE['http'], ct.DOMAINS['sf'], ct.PAGES['dl'], date, symbol), ct.TICK_SRCS[1] : ct.TICK_PRICE_URL_TT % (ct.P_TYPE['http'], ct.DOMAINS['tt'], ct.PAGES['idx'], symbol, datestr), ct.TICK_SRCS[2] : ct.TICK_PRICE_URL_NT % (ct.P_TYPE['http'], ct.DOMAINS['163'], date[0:4], datestr, symbol_dgt) } # 拼装分笔数据请求的URL 
代码 cons.py中对应内容 说明
ct.TICK_PRICE_URL TICK_PRICE_URL = ‘%smarket.%s/%s?date=%s&symbol=%s’ 新浪分笔数据请求
ct.DOMAINS[‘sf’] ‘sf’: ‘finance.sina.com.cn’ 数据来源新浪
ct.PAGES[‘dl’] ‘dl’: ‘downxls.php’ 数据来源页面
ct.TICK_PRICE_URL_TT TICK_PRICE_URL_TT = ‘%sstock.%s/data/%s?appn=detail&action=download&c=%s&d=%s’ 腾讯分笔数据请求
ct.DOMAINS[‘tt’] ‘tt’: ‘gtimg.cn’ 数据来源腾讯
ct.PAGES[‘idx’] ‘idx’: ‘index.php’ 数据来源页面
ct.TICK_PRICE_URL_NT TICK_PRICE_URL_NT = ‘%squotes.%s/cjmx/%s/%s/%s.xls’ 网易分笔数据请求
ct.DOMAINS[‘163’] ‘163’: ‘money.163.com’ 数据来源网易

新浪分笔数据请求示例:

http://market.finance.sina.com.cn/downxls.php?date=20200826&symbol=sh600000 

服务已经下线,可惜。
TuShare中源码分析(获取个股数据和基本面宏观数据)
腾讯分笔数据请求示例:

http://stock.gtimg.cn/data/index.php?appn=detail&action=download&c=sh600000&d=20200826 

请求的Excel数据如下:
TuShare中源码分析(获取个股数据和基本面宏观数据)

网易分笔数据请求示例:

http://quotes.money.163.com/cjmx/2020/20200826/0600000.xls 

说明:

http://quotes.money.163.com/cjmx/[今年年份]/[日期]/[股票代码].xls
返回结果:获取历史成交明细XLS文件。
注意,只能获取5日内的数据,之前的数据不会存在。
注意,该方法为网易公开获取数据方法,推荐使用。 

TuShare中源码分析(获取个股数据和基本面宏观数据)
下面代码是对爬取数据的处理

 for _ in range(retry_count): # 尝试爬取retry_count次
        time.sleep(pause) # 休眠pause秒 try: if src == ct.TICK_SRCS[2]: df = pd.read_excel(url[src]) # 操作读取excel文件
                df.columns = ct.TICK_COLUMNS else: re = Request(url[src]) # 请求打开URL页面
                lines = urlopen(re, timeout=10).read() # 保存返回页面内容到lines中
                lines = lines.decode('GBK') if len(lines) < 20: return None
                df = pd.read_table(StringIO(lines), names=ct.TICK_COLUMNS, skiprows=[0]) except Exception as e: print(e) else: return df
    raise IOError(ct.NETWORK_URL_ERROR_MSG) 

3、基本面数据

""" for trading data """ from tushare.stock.fundamental import (get_stock_basics, get_report_data, get_profit_data, get_operation_data, get_growth_data, get_debtpaying_data, get_cashflow_data, get_balance_sheet, get_profit_statement, get_cash_flow) 

上面代码说明TuShare的10个基本面数据API是从stock下的fundamental模块打包出来的。
我们打开源码stock目录下的fundamental.py文件,先分析fundamental.py的依赖项

import pandas as pd from tushare.stock import cons as ct	# 引入cons.py,包含股票相关常量定义 import lxml.html from lxml import etree import re import time from pandas.compat import StringIO from tushare.util import dateu as du	# 引入dateu.py,日期、交易日历的处理 try: from urllib.request import urlopen, Request
except ImportError: from urllib2 import urlopen, Request 

3.1、API:获取沪深上市公司基本情况

def get_stock_basics(date=None): 

代码中有获取获取沪深上市公司基本情况API的详细说明:

"""
        获取沪深上市公司基本情况
    Parameters
    date:日期YYYY-MM-DD,默认为上一个交易日,目前只能提供2016-08-09之后的历史数据

    Return -------- DataFrame
               code,代码
               name,名称
               industry,细分行业
               area,地区
               pe,市盈率
               outstanding,流通股本
               totals,总股本() totalAssets,总资产() liquidAssets,流动资产
               fixedAssets,固定资产
               reserved,公积金
               reservedPerShare,每股公积金
               eps,每股收益
               bvps,每股净资
               pb,市净率
               timeToMarket,上市日期 """ 
 wdate = du.last_tddate() if date is None else date	# 获取最后一个交易日
    wdate = wdate.replace('-', '') # 日期YYYY-MM-DD格式调整至YYYYMMDD格式 if wdate < '20160809': return None // 2016年8月9日之前没有数据 # 获取日期前缀,格式如:'201608/' datepre = '' if date is None else wdate[0:4] + wdate[4:6] + '/' # 拼接URL并Request
    request = Request(ct.ALL_STOCK_BASICS_FILE%(datepre, '' if date is None else wdate)) text = urlopen(request, timeout=10).read() # 保存返回的内容到text中
    text = text.decode('GBK') text = text.replace('--', '') df = pd.read_csv(StringIO(text), dtype={'code':'object'}) # 读取vsv文件
    df = df.set_index('code') # 设置code字段为索引 return df 

我们在dateu.py中找到last_tddate,这个函数用于获取最后一个交易日

def last_tddate(): today = datetime.datetime.today().date() # 获取当天的日期
    today=int(today.strftime("%w")) # %w 星期(0-6),获取当天是星期几 if today == 0: return day_last_week(-2) # 周日,返回上这个星期的两一天的日期(周五) else: return day_last_week(-1) # 非周日,返回上这个星期的上一天的日期 

我们在dateu.py中找到day_last_week,这个函数用于获取最后一个星期第几天的日期

def day_last_week(days=-7): lasty = datetime.datetime.today().date() + datetime.timedelta(days) return str(lasty) 
代码 cons.py中对应内容 说明
ct.ALL_STOCK_BASICS_FILE ALL_STOCK_BASICS_FILE = P_TYPE[‘http’] + DOMAINS[‘oss’] + ‘/tsdata/%sall%s.csv’ Tushare财经数据包拼接URL格式
DOMAINS[‘oss’] ‘oss’: ‘file.tushare.org’ Tushare财经数据包

示例,获取2020年8月26日的沪深上市公司基本情况:

http://file.tushare.org/tsdata/202008/all20200826.csv 

返回csv结果文件如下:
TuShare中源码分析(获取个股数据和基本面宏观数据)

3.2、API:获取业绩报表数据

我们打开源码stock目录下的fundamental.py文件,找到获取业绩报表数据API函数get_report_data

def get_report_data(year, quarter): 

代码中有获取业绩报表数据API的详细说明:

 """
        获取业绩报表数据
    Parameters -------- year:int 年度 e.g:2014 quarter:int 季度 :1234,只能输入这4个季度
       说明:由于是从网站获取的数据,需要一页页抓取,速度取决于您当前网络速度
       
    Return -------- DataFrame
        code,代码
        name,名称
        eps,每股收益
        eps_yoy,每股收益同比(%) bvps,每股净资产
        roe,净资产收益率(%) epcf,每股现金流量() net_profits,净利润(万元) profits_yoy,净利润同比(%) distrib,分配方案
        report_date,发布日期 """ 
 if ct._check_input(year,quarter) is True: # 检查输入的年度、季度是否准确
        ct._write_head() df = _get_report_data(year, quarter, 1, pd.DataFrame()) if df is not None: #             df = df.drop_duplicates('code') df['code'] = df['code'].map(lambda x:str(x).zfill(6)) return df 

我们在cons.py中找到_check_input,这个函数用于校验输入的年度、季度

def _check_input(year, quarter): if isinstance(year, str) or year < 1989 : # 年度不是字符串或年小于1989,抛出类型错误异常
        # DATE_CHK_MSG = '年度输入错误:请输入1989年以后的年份数字,格式:YYYY' raise TypeError(DATE_CHK_MSG) elif quarter is None or isinstance(quarter, str) or quarter not in [1, 2, 3, 4]: # 季度不是字符串或不是1234,抛出类型错误异常
        # DATE_CHK_Q_MSG = '季度输入错误:请输入1、2、3或4数字' raise TypeError(DATE_CHK_Q_MSG) else: return True 

我们在cons.py中找到_write_head,这个函数用于写头部标识

def _write_head(): sys.stdout.write(DATA_GETTING_TIPS) # DATA_GETTING_TIPS = '[Getting data:]' sys.stdout.flush() 

我们在fundamental.py中找到_get_report_data,这个函数用于获取业绩报表数据

def _get_report_data(year, quarter, pageNo, dataArr, retry_count=3, pause=0.001): 
参数 说明
year 年度
quarter 季度
pageNo 分页编码,编号从1开始
retry_count 爬取数据重连次数
pause 爬取数据重连时睡眠秒数
 ct._write_console() for _ in range(retry_count): time.sleep(pause) try: # 拼接获取业绩报表数据URL并Request
            request = Request(ct.REPORT_URL%(ct.P_TYPE['http'], ct.DOMAINS['vsf'], ct.PAGES['fd'], year, quarter, pageNo, ct.PAGE_NUM[1])) text = urlopen(request, timeout=10).read() # 保存业绩报表数据
            text = text.decode('GBK') text = text.replace('--', '') # 清除<td>--</td>格式数据
            html = lxml.html.parse(StringIO(text)) # 解析<table class="list_table" id="dataTable">中的数据内容
            res = html.xpath("//table[@class=\"list_table\"]/tr") if ct.PY3: sarr = [etree.tostring(node).decode('utf-8') for node in res] else: sarr = [etree.tostring(node) for node in res] sarr = ''.join(sarr) sarr = '<table>%s</table>'%sarr	# 把list_table中的数据再拼接成一个table
            # 通过read_html直接获取表格数据,得到table表格的list集合。
            df = pd.read_html(sarr)[0] df = df.drop(11, axis=1) df.columns = ct.REPORT_COLS # 把表格数据保存到DataFrame对象dataArr中
            dataArr = dataArr.append(df, ignore_index=True) nextPage = html.xpath('//div[@class=\"pages\"]/a[last()]/@onclick') if len(nextPage)>0: pageNo = re.findall(r'\d+', nextPage[0])[0] # 通过正则查找下一页的页码
                # 继续获取下一页的业绩报表数据 return _get_report_data(year, quarter, pageNo, dataArr) else: return dataArr
        except Exception as e: pass
    raise IOError(ct.NETWORK_URL_ERROR_MSG) 
代码 cons.py中对应内容 说明
ct.PORT_URL REPORT_URL = ‘%s%s/q/go.php/vFinanceAnalyze/kind/mainindex/%s?s_i=&s_a=&s_c=&reportdate=%s&quarter=%s&p=%s&num=%s’ 新浪业绩报表URL格式
ct.DOMAINS[‘vsf’] ‘vsf’: ‘vip.stock.finance.sina.com.cn’ 新浪财经股票数据中心
ct.PAGE_NUM[1] PAGE_NUM = [40, 60, 80, 100] 第页包含的数据记录条数

示例,获取2020年1季度的业绩报表数据:

http://vip.stock.finance.sina.com.cn/q/go.php/vFinanceAnalyze/kind/mainindex/2020?s_i=&s_a=&s_c=&reportdate=%s&quarter=1&p=1&num=40 

返回结果页面如下:
TuShare中源码分析(获取个股数据和基本面宏观数据)
我们查看页面源代码,业绩报表数据都在table中
TuShare中源码分析(获取个股数据和基本面宏观数据)

4、宏观数据

for macro data
"""
from tushare.stock.macro import (get_gdp_year, get_gdp_quarter,
                                 get_gdp_for, get_gdp_pull,
                                 get_gdp_contrib, get_cpi,
                                 get_ppi, get_deposit_rate,
                                 get_loan_rate, get_rrr,
                                 get_money_supply, get_money_supply_bal,
                                 get_gold_and_foreign_reserves) 

上面代码说明TuShare的13个宏观数据API是从stock下的macro模块打包出来的。
我们打开源码stock目录下的macro.py文件,先分析macro.py的依赖项

import pandas as pd import numpy as np import re import json from tushare.stock import macro_vars as vs	# 引入macro_vars.py,包含宏观数据相关常量定义 from tushare.stock import cons as ct		# 引入cons.py,包含股票相关常量定义 try: from urllib.request import urlopen, Request
except ImportError: from urllib2 import urlopen, Request 

4.1、API:获取年度国内生产总值数据

def get_gdp_year(): 

代码中有获取年度国内生产总值数据API的详细说明:

 """
        获取年度国内生产总值数据
    Return -------- DataFrame
        year :统计年度
        gdp :国内生产总值(亿元) pc_gdp :人均国内生产总值() gnp :国民生产总值(亿元) pi :第一产业(亿元) si :第二产业(亿元) industry :工业(亿元) cons_industry :建筑业(亿元) ti :第三产业(亿元) trans_industry :交通运输仓储邮电通信业(亿元) lbdy :批发零售贸易及餐饮业(亿元) """ 
 rdint = vs.random() # 拼接获取年度国内生产总值数据的URL request = Request(vs.MACRO_URL%(vs.P_TYPE['http'], vs.DOMAINS['sina'], rdint, vs.MACRO_TYPE[0], 0, 70, rdint)) text = urlopen(request, timeout=10).read() text = text.decode('gbk') if ct.PY3 else text
    regSym = re.compile(r'\,count:(.*?)\}') datastr = regSym.findall(text) datastr = datastr[0] datastr = datastr.split('data:')[1] datastr = datastr.replace('"', '').replace('null', '0') js = json.loads(datastr) df = pd.DataFrame(js, columns=vs.GDP_YEAR_COLS) df[df==0] = np.NaN return df 
代码 cons.py中对应内容 说明
vs.MACRO_URL MACRO_URL = ‘%smoney.finance.%s/mac/api/jsonp.php/SINAREMOTECALLCALLBACK%s/MacPage_Service.get_pagedata?cate=%s&event=%s&from=0&num=%s&condition=&_=%s’ 新浪获取年度国内生产总值数据URL格式
ct.DOMAINS[‘sina’] ‘sina’: ‘sina.com.cn’ 新浪财经股票数据中心
vs.MACRO_TYPE[0] MACRO_TYPE = [‘nation’,‘price’,‘fininfo’]

示例,获取年度国内生产总值数据:

http://money.finance.sina.com.cn/mac/api/jsonp.php/SINAREMOTECALLCALLBACK5564253726144/MacPage_Service.get_pagedata?cate=nation&event=0&from=0&num=70&condition=&_=5564253726144 

这个地址无法正常获取,代码还需要完善。
http://finance.sina.com.cn/mac/#nation-0-0-31-1中我们可以查看新浪的宏观数据,如果需要,我们需要自己扩展。

本文地址:https://blog.csdn.net/weixin_41245990/article/details/108242485