python-网络爬虫-爬取股票数据预测分析
一、课题研究背景与意义
有人把数据比喻为蕴藏能量的煤矿。煤炭按照性质有焦煤、无烟煤、肥煤、贫煤等分类,而露天煤矿、深山煤矿的挖掘成本又不一样。与此类似,大数据并不在“大”,而在于“有用”。价值含量、挖掘成本比数量更为重要。对于很多行业而言,如何利用这些大规模数据是赢得竞争的关键。在本文中,我们利用东方财富网上的股票数据作为我们的分析数据,对于过往的数据进行分析,为买家提供更多的信息和决策的依据。
股票的信息每秒钟都在发生变化,产生大量的数据。股票一直以来被认为是投机的行为。但是我们也可以从股票的一些信息数据中,发现其涨跌的规律。通过本次实验,我们想要发现影响股票的因素,以及投资那些股票可以获得较高的收益率,哪些因素可以反映股票是一支绩优股等。利用这些我们获取得到的信息,能够做出更加合理的决策。可以利用python平台,更加理性合理的分析股票涨跌的内在因素。用数据说话。
二、主题式网络爬虫设计方案
在本文中的数据集通过爬虫的方法,在东方财富网上的股票数据作为我们的分析数据。我们爬取的内容是东方财富网站上的股票数据。具体内容包括:。一些对于分析股票较为重要的内容。
整个系统主要由两大块组成:爬虫+可视化。首先我们会借助于python对于东方财富网站进行访问,并且爬取网页上关于股票的代码,名称,现价,动态市盈率,市净率,总市值,流通市值等信息。然后将所有的数据存入到excel表中进行统一的整合。爬虫部分就完成了,可视化的部分,是依托于python的matplotlib包进行,主要整合了现价,动态市盈率,市净率,总市值,流通市值的排名,还有现价和市净率之间是否存在线性关系进行了分析与讨论。
三、主题页面的结构特征分析
其网页如下图所示。可以看到在网站上,有股票的的名称,总市值等信息。的名字,这些详细的信息在后文中都会一一介绍,是如何爬取并且获得的。具体网页的代码,可以用开发者模式去看,有详细的CSS还有html代码,我们所要做的就是在这个代码中,获取到我们想要的信息。
四.基于python的股票数据可视化分析
1. 数据爬取与采集
在本文中,我们主要应用了python自带的urllib(urllib 库用于操作网页 URL,并对网页的内容进行抓取处理)和 BeautifulSoup这两个包进行爬取。其中Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
python2有urllib和urllib2两种模块,都用来实现网络请求的发送。python3将urllib和urllib2模块整合并命名为urllib模块。urllib模块有多个子模块,各有不同的功能:
①urllib.request模块:用于实现基本的http请求。
②urllib.error模块:用于异常处理。如在发送网络请求时出现错误,用该模块捕捉并处理。
Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:Tag、NavigableString、BeautifulSoup、Comment
Tag就是 HTML 中的一个个标签;得到了标签的内容用 .string 即可获取标签内部的文字。BeautifulSoup 对象表示的是一个文档的全部内容.大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称。爬取出来的结果我们用print打印出来。
2. 对数据进行清洗和处理
我们采用的是isnull函数来判断是否含有空值,并且将含有空值的函数去除。
3. 数据分析与可视化
通过上一章获得了在excel中的股票数据,下面就对其中的一些数据之间的相关性进行分析。利用matplotlib库我们进行了现价排名前7的股票的分析。可以看到,古井贡酒的现价排名第一超过了250.,形成了断层的现象。紧随其后的是湖州老窖,长春高新等。股票玩家可以考虑买一些白酒类的股票。
剩余的几张图和上述代码没有很大的差别,因此没有列出代码,将图表进行一一的展示。下图是动态市盈率的排名。南华生物以超过5000的动态市盈率排在了第一位。
1 #获取动态市盈率排名最高的前10名股票 2 sort_df = excel.sort_values(by="动态市盈率",ascending=[False]) 3 plt.rcParams["font.sans-serif"] = ["SimHei"] 4 plt.rcParams["axes.unicode_minus"] = False 5 6 index=sort_df ['名称'][:7] 7 values=sort_df ['动态市盈率'][:7] 8 plt.bar(index,values.values,color="green") 9 plt.title("动态市盈率排名") 10 # 设置x轴标签名 11 plt.xlabel("股票名称") 12 # 设置y轴标签名 13 plt.ylabel("现价") 14 # 显示 15 plt.show()
下面是对市净率进行分析,市净率,股价除以账面价值,可衡量该种股票的投资价值和投资风险。可以看到南华生物的市净率较高,因此不建议购入。
#获取市盈率排名最高的前几名股票
1 sort_df = excel.sort_values(by="市净率",ascending=[False]) 2 plt.rcParams["font.sans-serif"] = ["SimHei"] 3 plt.rcParams["axes.unicode_minus"] = False 4 5 index=sort_df ['名称'][:7] 6 values=sort_df ['市净率'][:7] 7 plt.bar(index,values.values,color="red") 8 plt.title("市净率排名") 9 # 设置x轴标签名 10 plt.xlabel("股票名称") 11 # 设置y轴标签名 12 plt.ylabel("现价") 13 # 显示 14 plt.show()
市场价格总值,可以市值的增加幅度或减少幅度来衡量该种股票发行公司的经营状况。可以看出排名前7的公司的市场价格总值非常不错。可以购入这几家的股票。
#获取排名总市值最高的前几名股票
1 sort_df = excel.sort_values(by="总市值",ascending=[False]) 2 plt.rcParams["font.sans-serif"] = ["SimHei"] 3 plt.rcParams["axes.unicode_minus"] = False 4 5 index=sort_df ['名称'][:7] 6 values=sort_df ['总市值'][:7] 7 plt.bar(index,values.values,color="pink") 8 plt.title("总市值排名") 9 # 设置x轴标签名 10 plt.xlabel("股票名称") 11 # 设置y轴标签名 12 plt.ylabel("现价") 13 # 显示 14 plt.show()
流通市值的排名中,美的集团的流通市值也是很高,因此在这些榜单中股票都可以考虑购入。
#获取排名流通市值最高的前几名股票
sort_df = excel.sort_values(by="流通市值",ascending=[False]) plt.rcParams["font.sans-serif"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False index=sort_df ['名称'][:7] values=sort_df ['流通市值'][:7] plt.bar(index,values.values,color="brown") plt.title("流通市值排名") # 设置x轴标签名 plt.xlabel("股票名称") # 设置y轴标签名 plt.ylabel("现价") # 显示 plt.show()
下面展示了现价和市净率的散点图,可以从图上粗略的看出,二者并没有很明显的线性关系。为了更加确定我们的结论,我们利用sklearn库中的线性回归函数进行求解。
可以从上述参数中看出,二者确实没有相似性的关系。
n = 250 area = 20*np.arange(1, n+1) # 5. 设置点的边界线宽度 【可选参数】 widths = np.arange(n)# 0-9的数字 x=excel["现价"] y=excel["市净率"] plt.scatter(x, y, s=area, linewidths=widths, alpha=0.5, marker='o') # 7. 设置轴标签:xlabel、ylabel #设置X轴标签 plt.xlabel('X坐标') #设置Y轴标签 plt.ylabel('Y坐标') # 8. 设置图标题:title plt.title('test绘图函数') # 9. 设置轴的上下限显示值:xlim、ylim # 设置横轴的上下限值 plt.xlim(-100, 100) # 设置纵轴的上下限值 plt.ylim(-100, 100) # 10. 设置轴的刻度值:xticks、yticks # 设置横轴精准刻度 plt.xticks(np.arange(np.min(x)-0.2, np.max(x)+0.2, step=0.3)) # 设置纵轴精准刻度 plt.yticks(np.arange(np.min(y)-0.2, np.max(y)+0.2, step=0.3)) # 也可按照xlim和ylim来设置 # 设置横轴精准刻度 plt.xticks(np.arange(-10,10 , step=0.5)) # 设置纵轴精准刻度 plt.yticks(np.arange(-10,10, step=0.5)) # plt.scatter(x, y)
4. 数据持久化
将所有股票的数据放入到datalist中作为最终我们爬取出来的数据。
为了方便我们读取看到的datalist数据,我们将datalist变量存放在excel表格中。在这里用到的是python中的xlwt包,进行excel表格的创建和读写。其代码如下:
其中xlwt包是python专门用于读取xls文件结尾的excel。通过上述的操作,我们将从爬虫得到的数据表单成功的放到了excel中。其可视化如下:
源码
1 import requests 2 3 import xlwt #进行excel操作 4 5 import xlrd 6 7 import numpy as np 8 9 from sklearn import datasets, linear_model 10 11 from sklearn.model_selection import train_test_split 12 13 from sklearn.metrics import mean_squared_error, r2_score 14 15 from sklearn.model_selection import cross_val_score 16 17 18 19 import sklearn.linear_model 20 21 import sklearn.datasets 22 23 import numpy as np 24 25 from sklearn.model_selection import train_test_split,cross_val_score 26 27 import matplotlib.pyplot as plt 28 29 from sklearn.metrics import mean_squared_error 30 31 32 33 url = 'http://27.push2.eastmoney.com/api/qt/clist/get' 34 35 datalist=[] 36 37 for i in range(1, 10): 38 39 data = { 40 41 'fields': 'f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152', 42 43 'pz': 1000, # 每页条数 44 45 'pn': i, # 页码 46 47 'fs': 'm:0 t:6,m:0 t:80,m:1 t:2,m:1 t:23,m:0 t:81 s:2048' 48 49 } 50 51 response = requests.get(url, data) 52 53 response_json = response.json() 54 55 print(i, response_json) 56 57 # 返回数据为空时停止循环 58 59 if response_json['data'] is None: 60 61 break 62 63 for j, k in response_json['data']['diff'].items(): 64 65 datas=[] 66 67 code = k['f12'] # 代码 68 69 name = k['f14'] # 名称 70 71 price = k['f2'] # 股价 72 73 pe = k['f9'] # 动态市盈率 74 75 pb = k['f23'] # 市净率 76 77 total_value = k['f20'] # 总市值 78 79 currency_value = k['f21'] # 流通市值 80 81 price = round(price/100, 2) # 价格转换为正确值(保留2位小数) 82 83 pe = round(pe/100, 2) # 市盈率转换为正确值(保留2位小数) 84 85 pb = round(pb/100, 2) # 市净率转换为正确值(保留2位小数) 86 87 total_value = round(total_value / 100000000, 2) # 总市值转换为亿元(保留2位小数) 88 89 currency_value = round(currency_value / 100000000, 2) # 流通市值转换为亿元(保留2位小数) 90 91 print('代码: %s, 名称: %s, 现价: %s, 动态市盈率: %s, 市净率: %s, 总市值: %s亿, 流通市值: %s'%(code,name,price,pe,pb,total_value,currency_value)) 92 93 datas.append(code) 94 95 datas.append(name) 96 97 datas.append(price) 98 99 datas.append(pe) 100 101 datas.append(pb) 102 103 datas.append(total_value) 104 105 datas.append(currency_value) 106 107 datalist.append(datas) 108 109 110 111 112 113 print("save......") 114 115 book=xlwt.Workbook(encoding='utf-8',style_compression=0) 116 117 sheet=book.add_sheet('stockers',cell_overwrite_ok=True) 118 119 col=('代码',"名称","现价","动态市盈率","市净率","总市值","流通市值") 120 121 for i in range(0,7): 122 123 sheet.write(0,i,col[i]) 124 125 for i in range(0,250): 126 127 print("第%d条"%i) 128 129 data=datalist[i] 130 131 for j in range(0,7): 132 133 sheet.write(i+1,j,data[j]) 134 135 136 137 138 139 140 141 book.save(".\\stockers.xls") 142 143 144 145 ###数据清洗 146 147 import pandas as pd 148 149 excel = pd.read_excel("stockers.xls") # 打开excel文件 150 151 152 153 # 1、是否存在空值 154 155 print(pd.isnull(excel.values)) 156 157 158 159 excel=excel.dropna() 160 161 162 163 ###### 164 165 ####数据可视化 166 167 import matplotlib.pyplot as plt 168 169 import numpy as np 170 171 #获取现价排名最高的前10名股票 172 173 sort_df = excel.sort_values(by="现价",ascending=[False]) 174 175 plt.rcParams["font.sans-serif"] = ["SimHei"] 176 177 plt.rcParams["axes.unicode_minus"] = False 178 179 180 181 182 183 index=sort_df ['名称'][:7] 184 185 values=sort_df ['现价'][:7] 186 187 plt.bar(index,values.values) 188 189 plt.title("现价排名") 190 191 # 设置x轴标签名 192 193 plt.xlabel("股票名称") 194 195 # 设置y轴标签名 196 197 plt.ylabel("现价") 198 199 # 显示 200 201 plt.show() 202 203 204 205 206 207 #获取动态市盈率排名最高的前10名股票 208 209 sort_df = excel.sort_values(by="动态市盈率",ascending=[False]) 210 211 plt.rcParams["font.sans-serif"] = ["SimHei"] 212 213 plt.rcParams["axes.unicode_minus"] = False 214 215 216 217 index=sort_df ['名称'][:7] 218 219 values=sort_df ['动态市盈率'][:7] 220 221 plt.bar(index,values.values,color="green") 222 223 plt.title("动态市盈率排名") 224 225 # 设置x轴标签名 226 227 plt.xlabel("股票名称") 228 229 # 设置y轴标签名 230 231 plt.ylabel("现价") 232 233 # 显示 234 235 plt.show() 236 237 238 239 240 241 sort_df = excel.sort_values(by="市净率",ascending=[False]) 242 243 plt.rcParams["font.sans-serif"] = ["SimHei"] 244 245 plt.rcParams["axes.unicode_minus"] = False 246 247 248 249 index=sort_df ['名称'][:7] 250 251 values=sort_df ['市净率'][:7] 252 253 plt.bar(index,values.values,color="red") 254 255 plt.title("市净率排名") 256 257 # 设置x轴标签名 258 259 plt.xlabel("股票名称") 260 261 # 设置y轴标签名 262 263 plt.ylabel("现价") 264 265 # 显示 266 267 plt.show() 268 269 270 271 272 273 sort_df = excel.sort_values(by="总市值",ascending=[False]) 274 275 plt.rcParams["font.sans-serif"] = ["SimHei"] 276 277 plt.rcParams["axes.unicode_minus"] = False 278 279 280 281 index=sort_df ['名称'][:7] 282 283 values=sort_df ['总市值'][:7] 284 285 plt.bar(index,values.values,color="pink") 286 287 plt.title("总市值排名") 288 289 # 设置x轴标签名 290 291 plt.xlabel("股票名称") 292 293 # 设置y轴标签名 294 295 plt.ylabel("现价") 296 297 # 显示 298 299 plt.show() 300 301 302 303 sort_df = excel.sort_values(by="流通市值",ascending=[False]) 304 305 plt.rcParams["font.sans-serif"] = ["SimHei"] 306 307 plt.rcParams["axes.unicode_minus"] = False 308 309 310 311 index=sort_df ['名称'][:7] 312 313 values=sort_df ['流通市值'][:7] 314 315 plt.bar(index,values.values,color="brown") 316 317 plt.title("流通市值排名") 318 319 # 设置x轴标签名 320 321 plt.xlabel("股票名称") 322 323 # 设置y轴标签名 324 325 plt.ylabel("现价") 326 327 # 显示 328 329 plt.show() 330 331 332 333 334 335 #250 336 337 n = 250 338 339 area = 20*np.arange(1, n+1) 340 341 # 5. 设置点的边界线宽度 【可选参数】 342 343 widths = np.arange(n)# 0-9的数字 344 345 346 347 x=excel["现价"] 348 349 y=excel["市净率"] 350 351 plt.scatter(x, y, s=area, linewidths=widths, alpha=0.5, marker='o') 352 353 # 7. 设置轴标签:xlabel、ylabel 354 355 #设置X轴标签 356 357 plt.xlabel('X坐标') 358 359 #设置Y轴标签 360 361 plt.ylabel('Y坐标') 362 363 # 8. 设置图标题:title 364 365 plt.title('test绘图函数') 366 367 # 9. 设置轴的上下限显示值:xlim、ylim 368 369 # 设置横轴的上下限值 370 371 plt.xlim(-100, 100) 372 373 # 设置纵轴的上下限值 374 375 plt.ylim(-100, 100) 376 377 # 10. 设置轴的刻度值:xticks、yticks 378 379 # 设置横轴精准刻度 380 381 plt.xticks(np.arange(np.min(x)-0.2, np.max(x)+0.2, step=0.3)) 382 383 # 设置纵轴精准刻度 384 385 plt.yticks(np.arange(np.min(y)-0.2, np.max(y)+0.2, step=0.3)) 386 387 # 也可按照xlim和ylim来设置 388 389 # 设置横轴精准刻度 390 391 plt.xticks(np.arange(-10,10 , step=0.5)) 392 393 # 设置纵轴精准刻度 394 395 plt.yticks(np.arange(-10,10, step=0.5)) 396 397 398 399 # 400 401 plt.scatter(x, y) 402 403 # 7. 设置轴标签:xlabel、ylabel 404 405 406 407 408 409 ########计算相关系数 410 411 412 413 import numpy as np 414 415 pc = np.corrcoef(x, y) 416 417 x=excel["现价"] 418 419 y=excel["市净率"] 420 421 print(pc) 422 423 424 425 426 427 import pandas as pd 428 429 from numpy import mean 430 431 #相关系数计算公式 432 433 def R_Square(x,y): 434 435 p1=x2=y2=0.0 436 437 #计算平均值 438 439 x_=mean(x) 440 441 y_=mean(y) 442 443 #循环读取每个值,计算对应值的累和 444 445 for i in range(len(x)): 446 447 p1+=(x[i]-x_)*(y[i]-y_) 448 449 x2+=(x[i]-x_)**2 450 451 y2+=(y[i]-y_)**2 452 453 #print(p1,x2,y2) 454 455 #计算相关系数 456 457 r=p1/((x2** 0.5)*(y2** 0.5)) 458 459 return r 460 461 #读取数据 462 463 df=pd.read_csv("data.csv",encoding='utf-8') 464 465 x=df['x'].tolist() 466 467 y=df['y'].tolist() 468 469 #调用并输出相关系数 470 471 print(R_Square(x,y)) 472 473 474 475 476 477 478 479 ###### 480 481 x=np.array(x) 482 483 x=x.reshape(-1,1) 484 485 X_train,X_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=0) 486 487 # 创建一个线性模型对象 488 489 regr = linear_model.LinearRegression() 490 491 print('交叉检验的R^2: ',np.mean(cross_val_score(regr,x,y,cv=3))) 492 493 # 用训练集训练模型fit(x,y,sample_weight=None)sample_weight为数组形状 494 495 regr.fit(X_train, y_train) 496 497 # 498 499 # 用测试集做一个预测 500 501 y_pred = regr.predict(X_test) 502 503 # 估计系数a 504 505 print("估计系数a: ", regr.coef_) 506 507 # 模型截距b 508 509 print("模型截距b: ",regr.intercept_) 510 511 # 均方误差即E(y_test-y_pred)^2 512 513 print("均方误差: " ,mean_squared_error(y_test, y_pred)) 514 515 # 决定系数r^2,越接近1越好 516 517 print("决定系数R^2: " ,r2_score(y_test, y_pred)) 518 519 520 521 #对比不同的划分系数 522 523 X_train,X_test,y_train,y_test=train_test_split(x,y,test_size=0.1,random_state=0) 524 525 # 创建一个线性模型对象 526 527 regr = linear_model.LinearRegression() 528 529 print('交叉检验的R^2: ',np.mean(cross_val_score(regr,x,y,cv=3))) 530 531 # 用训练集训练模型fit(x,y,sample_weight=None)sample_weight为数组形状 532 533 regr.fit(X_train, y_train) 534 535 # 536 537 # 用测试集做一个预测 538 539 y_pred = regr.predict(X_test) 540 541 # 估计系数a 542 543 print("估计系数a: ", regr.coef_) 544 545 # 模型截距b 546 547 print("模型截距b: ",regr.intercept_) 548 549 # 均方误差即E(y_test-y_pred)^2 550 551 print("均方误差: " ,mean_squared_error(y_test, y_pred)) 552 553 # 决定系数r^2,越接近1越好 554 555 print("决定系数R^2: " ,r2_score(y_test, y_pred)) 556 557 558 559 560 561 562 563 564 565 X_train,X_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=0) 566 567 # 创建一个线性模型对象 568 569 regr = linear_model.LinearRegression() 570 571 print('交叉检验的R^2: ',np.mean(cross_val_score(regr,x,y,cv=3))) 572 573 # 用训练集训练模型fit(x,y,sample_weight=None)sample_weight为数组形状 574 575 regr.fit(X_train, y_train) 576 577 # 578 579 # 用测试集做一个预测 580 581 y_pred = regr.predict(X_test) 582 583 # 估计系数a 584 585 print("估计系数a: ", regr.coef_) 586 587 # 模型截距b 588 589 print("模型截距b: ",regr.intercept_) 590 591 # 均方误差即E(y_test-y_pred)^2 592 593 print("均方误差: " ,mean_squared_error(y_test, y_pred)) 594 595 # 决定系数r^2,越接近1越好 596 597 print("决定系数R^2: " ,r2_score(y_test, y_pred))
总结
通过python的爬虫,在本文中成功的爬取了股票信息,利用了python中的urllib库,bs4,pandas等包。将股票信息进行爬取,然后存储到excel中。再用数据分析方法。
通过这次的系统的构建,对于python爬虫整体的构建有了深刻的理解,对于整个爬虫的流程也更加的熟练。首先先要确定我们所要爬取的网址,然后要模拟浏览器头部信息,向豆瓣服务器发送请求,不能暴露我们是借由python去爬虫。封装好之后获得我们请求。通过bs4里面的beautifulsoup作为我们的封装。通过正则表达式,我们从爬取的众多的信息中获取到我们需要的信息.也借此机会深刻的认识了正则表达式和正则表达式的用法。最后再用xlwt将我们的数据读取到excel中,用到了xlwt包。