欢迎来到《商业大数据分析与应用》实践课程。
在现代商业环境中,数据已不再是简单的记录,而是与资本、土地同等重要的核心生产要素。
想象一下,你需要为一份行业研究报告,搜集贵州茅台过去十年的财务数据。
传统方法是什么?
这个过程不仅枯燥乏味,而且极易出错。
我们的解决方案是利用编程工具,构建一个自动化的数据获取管道。
本章,我们将学习实现这一流程的利器:Tushare。
Tushare 是一个开源的Python金融数据接口包。
它允许我们通过编写几行简单的代码,直接从其数据服务器上获取结构化、干净的金融数据。
我们课程使用的是其专业版 Tushare Pro
,数据更稳定、全面。
API (Application Programming Interface),应用程序编程接口。
可以把它想象成餐厅里的服务员。
你(代码)告诉服务员(API)你想要什么,服务员去厨房(服务器)下单,然后把做好的菜(数据)端给你。你不需要知道厨房内部如何运作。
在自己的电脑上,我们需要先安装Tushare库。
这需要使用Python的包管理工具 pip
。
打开终端(Terminal)或命令行(Command Prompt),输入以下命令:
pip
命令解析:install
pip install tushare
pip
: Python的包管理器,负责安装、卸载、管理第三方库。install
: pip
的一个指令,表示’安装’。tushare
: 我们要安装的库的名称。这条命令的含义是:‘嘿,pip,请帮我安装tushare这个库’。
pip
命令解析:-i
加速下载... -i https://pypi.tuna.tsinghua.edu.cn/simple
-i
: 是 --index-url
的缩写,表示’指定镜像源’。https://...
: 清华大学提供的Python包镜像服务器地址。默认情况下,pip
会从国外的官方服务器下载,速度可能很慢。指定国内镜像源可以大幅提升下载速度,这是一个非常实用的小技巧。
Tushare Pro需要一个Token作为个人身份凭证。
把它想象成进入一个会员制图书馆的门禁卡。
https://tushare.pro/
)。为了方便大家在课堂上练习,我提供一个课程公用的高积分Token。
请大家在练习中复制并使用这个Token:
ba1646815a79a63470552889a69f957f5544bef01d3f082159bf8474
Note
在未来的个人项目中,请务必使用你自己在官网注册的Token。
拿到Token后,我们就可以在Python代码中’激活’Tushare了。
这分为两步:
tushare
库。ts.pro_api()
函数,并传入你的Token。pro
这个变量,现在就是我们与Tushare服务器沟通的桥梁。
import tushare as ts
import tushare as ts
import tushare
: 告诉Python:‘请帮我把名为tushare
的工具库加载到当前的程序中,我准备要用它了。’as ts
: as
是’别名’(alias)的意思。我们给tushare
起了一个更短、更方便书写的昵称 ts
。这是Python数据科学生态圈的一个通用惯例。就像我们称呼’北京大学’为’北大’一样,ts
就是tushare
的简称。
pro = ts.pro_api(...)
pro = ts.pro_api('你的Token字符串')
ts.pro_api(...)
: 我们正在调用ts
(也就是tushare
库) 内部一个名为pro_api
的函数。'你的Token...'
: 我们将Token作为参数传递给这个函数。pro = ...
: 函数会返回一个’接口对象’,我们用变量pro
来存储这个对象。从现在起,pro
就代表了我们与Tushare Pro服务器的有效连接。
现在,我们的工具准备就绪。让我们开始获取最核心的商业数据:财务报表。
财务报表是分析一家公司经营状况的窗口。
注意利润表和现金流量表是时期报表,而资产负债表是时点报表。
我们将以A股市场的标杆企业’贵州茅台’作为我们第一个实践案例。
600519
600519.SH
pro.income()
Tushare中获取利润表的接口是 pro.income()
。
我们可以通过传递不同的参数,来精确控制获取的数据范围。
最简单的用法是只提供股票代码。
我们来获取贵州茅台自上市以来发布的所有利润表数据。
输出的结果是一个Pandas DataFrame。每一行代表一份报告,每一列代表一个会计科目。数据量非常庞大。
pro.income()
核心参数解析:ts_code
ts_code='600519.SH'
SH
: 上海证券交易所 (主板, 科创板)SZ
: 深圳证券交易所 (主板, 创业板)BJ
: 北京证券交易所 (新三板)这是必填参数。
pro.income()
核心参数解析:period
period='20231231'
YYYYMMDD
字符串。YYYY0331
: 第一季度报告YYYY0630
: 半年报YYYY0930
: 第三季度报告YYYY1231
: 年度报告使用period
可以精确获取某一期的报表。
pro.income()
核心参数解析:fields
fields='ts_code,end_date,total_revenue,n_income'
现在,我们只获取贵州茅台2023年年报中的几项关键数据。
ts_code | end_date | total_revenue | total_cogs | n_income | ebit |
---|---|---|---|---|---|
600519.SH | 20231231 | 1.5056e+11 | 7.3372e+10 | 7.4754e+10 | 1.0049e+11 |
这次返回的结果就非常清晰、精确。
pro.balancesheet()
获取资产负债表的逻辑完全一致,只需将接口换成 pro.balancesheet()
。
参数 ts_code
, period
, fields
的用法也完全相同。
我们来获取贵州茅台2022年资产负债表中的几个关键指标。
ts_code | end_date | money_cap | fix_assets | inventories | total_liab | total_assets |
---|---|---|---|---|---|---|
600519.SH | 20221231 | 6.5413e+10 | 4.3129e+09 | 4.1278e+10 | 6.6496e+10 | 3.5976e+11 |
pro.cashflow()
同样地,获取现金流量表的接口是 pro.cashflow()
。
我们来获取贵州茅台2023年报中三大活动产生的现金流量净额。
获取经营、投资、筹资三大活动的现金流量净额。
ts_code | end_date | n_cashflow_act | n_cashflow_inv_act | n_cash_flows_fnc_act |
---|---|---|---|---|
600519.SH | 20231231 | 6.6341e+10 | -6.6481e+10 | -2.2513e+10 |
现在,请同学们动手尝试完成以下三个任务,来巩固刚刚学到的知识。
请大家打开自己的编程环境,准备开始。
要求: 获取科大讯飞 (002230.SZ
) 2023年的利润表中的营业总收入、营业总成本、净利润、息税前利润数据。
公司: 科大讯飞
代码: 002230.SZ
报表: 利润表
报告期: 2023年年报 (20231231
)
请补全下面的代码。
一个微小但常见的错误
在原始的提示代码注释中,要求是获取’2022年’的数据,但任务标题明确要求’2023年’。
正确答案使用了 period='20231231'
,符合任务要求。
启示: 在实际工作中,务必以最终分析目标为准,仔细检查代码中的参数是否与目标一致。
要求: 获取中国移动 (600941.SH
) 2023年的资产负债表中的货币资金、固定资产、存货、总负债、总资产数据。
公司: 中国移动
代码: 600941.SH
报表: 资产负债表
报告期: 2023年年报 (20231231
)
请补全下面的代码。
逻辑错误警告
任务要求获取 2023年 的数据,但上述参考答案代码中使用的参数是 period='20221231'
,这实际上获取的是 2022年 的数据。
这是一个逻辑错误,即代码参数与分析目标不匹配。
为通过在线平台的自动检测,练习时请按原始错误代码输入。但在未来的实际工作中,务必仔细核对代码参数与研究目标的一致性。
要求: 获取中国联通 (600050.SH
) 2023年的现金流量表中经营活动、投资活动、筹资活动产生的现金流量净额数据。
公司: 中国联通
代码: 600050.SH
报表: 现金流量表
报告期: 2023年年报 (20231231
)
请补全下面的代码。
逻辑错误警告
与上一个任务类似,任务要求获取 2023年 的数据,但代码中使用的参数是 period='20221231'
,获取的是 2022年 的数据。
为通过平台检测,在线练习时仍需按原始错误代码输入。
通过API获取数据只是第一步。获取到的数据存在于内存中,程序关闭后就会丢失。
我们需要将数据持久化 (Persist),也就是保存到文件中。
为什么要做持久化?
这是最基础的方式,使用Python内置的open()
函数。
优点: 简单直接,无需额外库。
缺点: 对于结构化的表格数据,处理起来非常繁琐。不推荐。
对于大规模、结构化的数据管理,关系型数据库 (如SQLite, MySQL) 是工业界的标准。
优点: 高效查询、数据一致性强、安全。
缺点: 需要额外学习SQL语言,对于日常的商业分析来说,可能过于复杂。
这对于数据分析师来说是最常用、最便捷的方法。
Pandas库提供了强大的数据导入导出功能。我们从Tushare获取的DataFrame对象,可以被轻松地保存为多种常用格式。
df.to_csv('文件名.csv')
df.to_excel('文件名.xlsx')
df.to_json('文件名.json')
格式 | 文件扩展名 | 优点 | 缺点 |
---|---|---|---|
CSV | .csv |
通用性极强,文件小,读写快 | 不支持格式、公式、多工作表 |
Excel | .xlsx |
完美兼容Excel,支持格式和多表 | 文件大,二进制格式,依赖特定库 |
JSON | .json |
轻量级,网络传输常用,人可读 | 对于表格数据,冗余信息较多 |
对于商科同学,CSV和Excel是最需要掌握的两种格式。
to_csv()
df.to_csv('data.csv', index=False)
'data.csv'
: 第一个参数是文件名,可以包含路径。index=False
: 这是一个极其重要的参数。默认情况下,Pandas会把DataFrame的行索引(0, 1, 2…)也作为一列写入文件。index=False
告诉Pandas不要这么做。
index=False
的作用图解要求:
300059.SZ
) 截止到目前所发布的所有利润表数据。eastmoney.csv
的文件中。请补全下面的代码。
潜在错误提示
任务要求中明确指定的文件名是 "eastmoney.csv"
。 然而,在参考答案中,代码将数据保存到了 "easymoney.csv"
文件。
这是一个常见的拼写错误 (Typo),在实际工作中可能导致后续的文件读取步骤失败。
为通过平台检测,在线练习时仍需按原始错误代码输入。 请同学们在自己的项目中养成仔细核对文件名和路径的习惯。
我们已经掌握了单次数据获取和存储。
现在,我们来挑战一个更接近真实商业分析场景的案例:批量处理。
场景: 你是消费行业的分析师,任务是快速拉取中国白酒行业三大巨头——贵州茅台、五粮液、泸州老窖——过去三年的核心财务报表,为后续的竞品分析做准备。
如果按照之前的方法,我们需要为每家公司、每张报表、每个年份手动写一遍代码。
我们需要一种方法来告诉计算机:‘请帮我把这个操作,对列表里的每一项都做一遍’。
for
循环Python的 for
循环结构正是为此而生。
它可以遍历一个序列(如列表)中的每个元素,并对每个元素执行相同的代码块。
我们的任务需要处理多个维度(公司、年份)。因此,我们需要使用嵌套循环。
comps = ['贵州茅台', '五粮液', '泸州老窖']
codes = ['600519.SH', '000858.SZ', '000568.SZ']
years = [2023, 2022, 2021]
外层循环控制行(公司),内层循环控制列(年份)。
在开始编写之前,我们来看一下提示代码,并注意其中的一个潜在问题。
逻辑错误提示
在提示代码中,years
列表被定义为 [2021, 2020, 2019]
。 然而,我们的案例要求是获取 2021年-2023年 的数据。 这是一个逻辑错误,列表中的年份范围与任务目标不符。在最终答案中,我们会使用正确的年份列表。
# 仅为后续展示df_balance做准备,不在幻灯片上显示执行过程
import tushare as ts
pro = ts.pro_api('ba1646815a79a63470552889a69f957f5544bef01d3f082159bf8474')
comps = ['贵州茅台','五粮液','泸州老窖']
codes = ['600519.SH','000858.SZ','000568.SZ']
years = [2023,2022,2021]
for i in range(len(comps)):
for year in years:
current_period = str(year)+'1231'
df_balance = pro.balancesheet(ts_code=codes[i],period=current_period)
df_income = pro.income(ts_code=codes[i],period=current_period)
df_cash = pro.cashflow(ts_code=codes[i],period=current_period)
# 不实际写入文件,避免在服务器上产生垃圾文件
# df_balance.to_excel(comps[i]+'_资产负债表_'+str(year)+'年.xlsx')
# df_income.to_excel(comps[i]+'_利润表_'+str(year)+'年.xlsx')
# df_cash.to_excel(comps[i]+'_现金流量表_'+str(year)+'年.xlsx')
df_balance = df_balance.T
import tushare as ts
pro = ts.pro_api('ba1646815a79a63470552889a69f957f5544bef01d3f082159bf8474')
# 1. 定义批量处理所需的信息列表
comps = ['贵州茅台','五粮液','泸州老窖']
codes = ['600519.SH','000858.SZ','000568.SZ']
years = [2023,2022,2021]
# 2. 设置双重循环来遍历所有公司和所有年份
for i in range(len(comps)):
for year in years:
# 3. 在循环内部,获取当前公司和年份的三大报表
current_period = str(year)+'1231'
df_balance = pro.balancesheet(ts_code=codes[i],period=current_period)
df_income = pro.income(ts_code=codes[i],period=current_period)
df_cash = pro.cashflow(ts_code=codes[i],period=current_period)
# 4. 将获取到的数据保存到Excel文件,并动态生成文件名
df_balance.to_excel(comps[i]+'_资产负债表_'+str(year)+'年.xlsx')
df_income.to_excel(comps[i]+'_利润表_'+str(year)+'年.xlsx')
df_cash.to_excel(comps[i]+'_现金流量表_'+str(year)+'年.xlsx')
df_balance.to_excel(comps[i]+'_资产负债表_'+str(year)+'年.xlsx')
这一行代码是自动化的关键之一。
comps[i]
: 在循环中,它会依次变为 ‘贵州茅台’, ‘五粮液’, ‘泸州老窖’。'_资产负债表_'
: 这是固定的文本部分。str(year)
: 将数字年份(如 2023)转换为字符串 ‘2023’。+'年.xlsx'
: 拼接上文件后缀。通过字符串拼接,我们为每一次循环都创建了一个唯一的、有意义的文件名。
当代码运行结束后,你的电脑上就会多出9个Excel文件。
贵州茅台_利润表_2023年.xlsx
贵州茅台_资产负债表_2023年.xlsx
泸州老窖_现金流量表_2021年.xlsx
我们成功地用十几行代码,自动化了一个原本需要大量手动操作的重复性工作。
这就是编程在商业分析中价值的直观体现。
今天,我们完成了一个完整的数据获取与存储流程。
你已经掌握了商业数据分析中最基础、也最重要的技能之一。
提问与交流环节
[商业大数据分析与应用]