快来看看招商银行理财产品数据(代码及分析)

前言

近段时间经常收到招商银行关于理财相关的短信,看来我已成了招行的目标客户(虽然我还很穷~)。穷归穷,看看还是不花钱的,于是前往招行的理财产品网站看看,嚯!足足上千种理财产品,让我迸发了了解数据的冲动。于是乎,按照分析师的习惯,先从网站抓取数据,然后基于获得的数据作一个探究

数据爬虫

当你来到对方的理财产品网站,你会发现网页中的数据并没有直接的存储在网页源代码中,因为当我不停的下拉,并点击下一页时,其链接并没有发生变化。OK,那这样看来,数据一定是作了异步存储,接下来找到这个异步存储数据的链接才是最关键的。下面,把寻找目标链接的方法作一一说明:

  • 使用Chrome浏览器,打开链接:http://www.cmbchina.com/cfweb/personal/default.aspx

  • 按F12键,选择“Network”选项,并点击网页中的下一页

  • “XHR”中你会出现一个文件,去点击它
  • 选择“Preview”预览,发现数据

  • 双击“XHR”中的文件,得到数据链接

接下来要做的就是,发现链接中的规律,调整链接中对应的“pageindex”,得到不同页下的数据,具体爬虫代码如下:

# ===== Python3 =====# 导入第三方包

importrequests

importre

importtime

importpandas aspd

importnumpy asnp

importmatplotlib.pyplot asplt

importmatplotlib.mlab asmlab

# 设置请求头

headers = { ‘Accept’: ‘*/*’, ‘Accept-Encoding’: ‘gzip, deflate’, ‘Accept-Language’: ‘zh-CN,zh;q=0.9’, ‘Connection’: ‘keep-alive’, ‘User-Agent’: ‘Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36’}

# 拼接URL,用于翻页爬虫

url_phase1 = ‘http://www.cmbchina.com/cfweb/svrajax/product.ashx?op=search&type=m&pageindex=’

url_phase2 = ‘&salestatus=&baoben=&currency=&term=&keyword=&series=01&risk=&city=&date=&pagesize=40&orderby=ord1&t=0.8683289736280901’

urls = [] fori inrange( 1, 29): urls.append(url_phase1+str(i)+url_phase2)

# 构造空列表,用于后面的数据存储

Finacing = []

# 通过for循环完成URL的遍历

forurl inurls:

# 获取源代码res = requests.get(url, headers = headers).text

# 正则表达式完成信息的获取ProdCode = re.findall( ‘PrdCode:”(.*?)”,’,text) ProdName = re.findall( ‘PrdName:”(.*?)”,’,text) TypeCode = re.findall( ‘TypeCode:”(.*?)”,’,text) AreaCode = re.findall( ‘AreaCode:”(.*?)”,’,text) BeginDate = re.findall( ‘BeginDate:”(.*?)”,’,text) EndDate = re.findall( ‘EndDate:”(.*?)”,’,text) ExpireDate = re.findall( ‘ExpireDate:”(.*?)”,’,text) Status = re.findall( ‘Status:”(.*?)”,’,text) NetValue = re.findall( ‘NetValue:”(.*?)”,’,text) IsNewFlag = re.findall( ‘IsNewFlag:”(.*?)”,’,text) NetValue = re.findall( ‘NetValue:”(.*?)”,’,text) Term = re.findall( ‘Term:”(.*?)”,’,text) Style = re.findall( ‘Style:”(.*?)”,’,text) InitMoney = re.findall( ‘InitMoney:”(.*?)”,’,text) IncresingMoney = re.findall( ‘IncresingMoney:”(.*?)”,’,text) Risk = re.findall( ‘Risk:”(.*?)”,’,text) FinDate = re.findall( ‘FinDate:”(.*?)”,’,text) SaleChannel = re.findall( ‘SaleChannel:”(.*?)”,’,text) SaleChannelName = re.findall( ‘SaleChannelName:”(.*?)”,’,text) IsCanBuy = re.findall( ‘IsCanBuy:”(.*?)”}’,text)

# 数据存储到字典中Finacing.append({ ‘ProdCode’:ProdCode, ‘ProdName’:ProdName, ‘TypeCode’:TypeCode, ‘AreaCode’:AreaCode,

‘BeginDate’:BeginDate, ‘EndDate’:EndDate, ‘ExpireDate’:ExpireDate, ‘Status’:Status,

‘NetValue’:NetValue, ‘IsNewFlag’:IsNewFlag, ‘NetValue’:NetValue, ‘Term’:Term,

‘Style’:Style, ‘InitMoney’:InitMoney, ‘IncresingMoney’:IncresingMoney, ‘Risk’:Risk,

‘FinDate’:FinDate, ‘SaleChannel’:SaleChannel, ‘SaleChannelName’:SaleChannelName, ‘IsCanBuy’:IsCanBuy})

# 睡眠3秒time.sleep( 3)

# 将数据转换为数据框

CMB_Finance = pd.concat([pd.DataFrame(data) fordata inFinacing])

# 数据导出

CMB_Finance.to_excel( ‘CMB_Finance.xlsx’, index = False)

很快就可以把招商银行网站中的1000多种理财产品全部获取回来。接下来要做的就是数据的探索性分析,了解数据的特征和分布。

探索性分析

如果你没有完成上面的爬虫也没有关系,本文后面提供了数据集下载的链接,你可以通过读取的方式进行这部分的探索性分析。

  • 数据类型转换

# 读取数据

cmb = pd.read_excel( ‘CMB_Finance.xlsx’)

# 查看数据集的行列数

cmb.shape

# 查看数据前几行

cmb.head()

# 查看数据集的数据类型c

mb.dtypes

从爬下来的数据表来看,除了InitMoney(最低投资额)、IncresingMoney(投资增加额)和TypeCode(产品类型编码)是数值型的,其他都是字符串型。这里,我们是可以把FinDate(期限)和NetValue(收益率)字段转换为数值型的。

# 数据类型转换# 将FinDate(期限)字段转换为数值型

cmb.FinDate = cmb.FinDate.str[:- 1].astype( ‘int’)

# 将NetValue(收益率)字段转换为数值型

cmb.NetValue = cmb.NetValue.str[:- 1].astype( ‘float’)/ 100

  • 收益率最高和最低的3种产品

对于大部分理财用户来说,都会非常关心理财产品的收益率,虽然都知道高风险高收益,但还是会权衡收益率最高的产品和最低的产品。接下来,我们借助于条形图来展示收益率:

# 预期收益率最高的3个产品

NetValue_sort_desc = cmb[[ ‘ProdCode’, ‘NetValue’]].sort_values(by = ‘NetValue’, ascending= False)NetValue_duplicate_top = NetValue_sort_desc.drop_duplicates(subset = ‘NetValue’).head( 3)

# 预期收益率最低的3个产品

NetValue_sort_asc = cmb[[ ‘ProdCode’, ‘NetValue’]].sort_values(by = ‘NetValue’, ascending= True)NetValue_duplicate_last = NetValue_sort_asc.drop_duplicates(subset = ‘NetValue’).head( 3)

# 中文和负号的正常显示

plt.rcParams[ ‘font.sans-serif’] = [ ‘Microsoft YaHei’]plt.rcParams[ ‘axes.unicode_minus’] = False

# 设置图形的显示风格

plt.style.use( ‘ggplot’)

# 为了让多张子图在一张图中完成,设置子图的位置

ax1 = plt.subplot2grid(( 2, 1),( 0, 0))ax2 = plt.subplot2grid(( 2, 1),( 1, 0))

# 绘制条形图

ax1.bar(range( 3), NetValue_duplicate_top.NetValue, align = ‘center’, color = ‘steelblue’, alpha = 0.7)

# y轴范围

ax1.set_ylim( 0.045, 0.051)

# x轴刻度标签

ax1.set_xticks(np.arange( 3)) ax1.set_xticklabels(NetValue_duplicate_top.ProdCode)

# x轴标签

ax1.set_xlabel( ‘产品编号’)

# y轴刻度标签

ax1.set_yticks(np.arange( 0.045, 0.051, 0.001))ax1.set_yticklabels([str(i* 100) + ‘%’fori innp.arange( 0.045, 0.051, 0.001)])

# y轴标签

ax1.set_ylabel( ‘预期收益率’)

# 标题

ax1.set_title( ‘预期收益率最高的5类产品’)ax2.bar(range( 3), NetValue_duplicate_last.NetValue, align = ‘center’,color = ‘steelblue’, alpha = 0.7)ax2.set_ylim( 0.045, 0.048)ax2.set_xticks(np.arange( 3)) ax2.set_xticklabels(NetValue_duplicate_last.ProdCode)

# x轴标签

ax2.set_xlabel( ‘产品编号’)

# y轴刻度标签

ax2.set_yticks(np.arange( 0.045, 0.048, 0.001)) ax2.set_yticklabels([str(i* 100) + ‘%’fori innp.arange( 0.045, 0.048, 0.001)])

# y轴标签

ax2.set_ylabel( ‘预期收益率’)ax2.set_title( ‘预期收益率最低的5类产品’)

# 调整子图之间的高度间距

plt.subplots_adjust(hspace= 0.5)

# 去除图形顶部边界和右边界的刻度

plt.tick_params(top= ‘off’, right= ‘off’)

# 图形显示

plt.show()

图中显示,最高的收益率可以达到5%,最低的收益率为4.6%(肯定都比存银行的收益率都高吧~)。

  • 理财产品风险类型分布

从表中我们得知,这1000多种产品分为三种风险类型,分别是谨慎性、稳健性和平稳性,他们之间的比例如何呢?我们通过饼图来呈现这个比例:

# 先对各风险类型的样本量作统计

stats = cmb.Risk.value_counts()plt.axes(aspect= ‘equal’)

# 控制x轴和y轴的范围

plt.xlim( 0, 4)plt.ylim( 0, 4)explode = [ 0, 0, 0.1,]

colors=[ ‘#9999ff’, ‘#ff9999’, ‘#7777aa’] # 自定义颜色

# 绘制饼图

plt.pie(x = stats.values, # 绘图数据explode=explode, # 突出显示谨慎性产品labels=stats.index, # 添加教育水平标签colors=colors, # 设置饼图的自定义填充色autopct= ‘%.1f%%’, # 设置百分比的格式,这里保留一位小数pctdistance= 0.8, # 设置百分比标签与圆心的距离labeldistance = 1.15, startangle = 180, # 设置饼图的初始角度radius = 1.5, # 设置饼图的半径counterclock = False, # 是否逆时针,这里设置为顺时针方向wedgeprops = { ‘linewidth’: 1.5, ‘edgecolor’: ‘green’}, # 设置饼图内外边界的属性值textprops = { ‘fontsize’: 12, ‘color’: ‘k’}, # 设置文本标签的属性值center = ( 1.8, 1.8), # 设置饼图的原点frame = 1) # 是否显示饼图的图框,这里设置显示

# 删除x轴和y轴的刻度

plt.xticks(())plt.yticks(())

# 添加图标题

plt.title( ‘理财产品风险类型分布’)

# 显示图形

plt.show()

上图显示,谨慎性的产品是最少的,只有10%。这个也比较容易理解,毕竟银行也是想从更多的风险投资人那边获得更多的利益,而谨慎性的产品(收益率不会高,并且是浮动收益)应该是用来起吆喝,吸流量的作用(毕竟大部分人还是停留在保值的心理阶段)。

  • 理财产品期限的描述性统计

接下来我们来了解一下,这些理财产品的期限FinDate,上面已经将该变量转换为数值型了,首先对改变了作一下描述性统计

# 理财产品期限的描述性统计

cmb.FinDate.describe()

我们发现,这些理财产品的平均期限为半年(180天),而且四分之三的产品也是在180天以内。我想这应该是招商银行做过统计,例如,什么样的理财产品好卖,这些产品在消费者手中的持有时间都是多少天等。同时,我们也可以针对这个期限作一个直方图,来看看时间上的分布特征:

# 理财产品期限的直方图

plt.hist(cmb.FinDate, # 绘图数据bins = np.arange(cmb.FinDate.min(),cmb.FinDate.max(), 30), # 指定直方图的组距normed = True, # 设置为频率直方图color = ‘steelblue’, # 指定填充色edgecolor = ‘k’) # 指定直方图的边界色

# 设置坐标轴标签和标题

plt.title( ‘理财产品期限直方图’)plt.xlabel( ‘期限(天数)’)plt.ylabel( ‘频率’)

# 生成正态曲线的数据

x1 = np.linspace(cmb.FinDate.min(), cmb.FinDate.max(), 1000)normal = mlab.normpdf(x1, cmb.FinDate.mean(), cmb.FinDate.std())

# 绘制正态分布曲线

line1, = plt.plot(x1,normal, ‘r-‘, linewidth = 2) # 生成核密度曲线的数据

kde = mlab.GaussianKDE(cmb.FinDate)x2 = np.linspace(cmb.FinDate.min(), cmb.FinDate.max(), 1000)

# 绘制

line2, = plt.plot(x2,kde(x2), ‘g-‘, linewidth = 2)

# 去除图形顶部边界和右边界的刻度

plt.tick_params(top= ‘off’, right= ‘off’)

# 显示图例

plt.legend([line1, line2],[ ‘正态分布曲线’, ‘核密度曲线’],loc= ‘best’)

# 显示图形

plt.show()

不错所料,期限呈现严重的右偏特征,这也是绝大多数经济活动的共性,如消费频次越多的人肯定越少;花费金额越多的人也肯定越少。

  • 基于风险类型的期限分布

我们可以进一步细化,看看不同类型风险的产品,是不是产品期限存在明显的差异,这里我们就借助于箱线图做一个比较:

# 如果将其划分到不同的Risk(风险类型)中,期限的分布是否存在差异

FinDate = []Risks = cmb.Risk.unique()Risks.sort()

forRisk inRisks: FinDate.append(cmb.loc[cmb.Risk==Risk, ‘FinDate’])

# 绘图

plt.boxplot(x = FinDate, patch_artist=True, labels = Risks, # 添加具体的标签名称showmeans=True, boxprops = { ‘color’: ‘black’, ‘facecolor’: ‘#9999ff’}, flierprops = { ‘marker’: ‘o’, ‘markerfacecolor’: ‘red’, ‘color’: ‘black’}, meanprops = { ‘marker’: ‘D’, ‘markerfacecolor’: ‘indianred’}, medianprops = { ‘linestyle’: ‘–‘, ‘color’: ‘orange’})

# 设置坐标轴标签和标题

plt.title( ‘不同风险类型下的产品期限差异盒形图图’)plt.xlabel( ‘风险类型’)plt.ylabel( ‘期限’)

# 去除图形顶部边界和右边界的刻度

plt.tick_params(top= ‘off’, right= ‘off’)

# 显示图形

plt.show()

图中显示,不同风险类型的理财产品确实在期限上存在差异,对于平衡性的产品,平均期限在500天左右,而稳健性和谨慎性的平均期限只有110天和170天。

结语

OK,今天关于数据爬虫和数据的探索性分析就分享到这里,希望感兴趣的朋友能够照着做一遍,相信对你一定有帮助。如果你有任何问题,欢迎在公众号的留言区域表达你的疑问。同时,也欢迎各位朋友继续转发与分享文中的内容,让更多的人学习和进步。

  • 文内代码及数据

链接: https://pan.baidu.com/s/1mi1hUtE 密码: ya9v

 

END.

You may also like...

发表评论

切换注册

登录

忘记密码 ?

切换登录

注册