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包。

posted @ 2022-12-21 14:37  蔡毓原  阅读(1321)  评论(0编辑  收藏  举报