一、前言
最近学了基础爬虫,以及在书本中了解到了Python中情感分析的库snownlp,所以便自己写了个爬虫爬取了一支股票的评论及涨跌幅,从而进行分析两者间的关系。
二、爬取股票评论
我是在东方财富的股吧去爬取评论的,但是里面掺杂着一些官方消息等,所以在利用snownlp分析时,官方消息的情感评分较高,所以对结果产生了一点影响,但是问题不大,最后还是可以得到想要的结果的。
代码如下:
import requests
from lxml import etree
import pandas as pd
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36'
}
list_text = []
list_time = []
#爬取相应页面的评论
for page in range(1,29):
url = 'http://guba.eastmoney.com/list,600026_' + str(page) + '.html'
page_text = requests.get(url=url,headers=headers).text
tree = etree.HTML(page_text)
#爬取相应的评论
list_text_span = tree.xpath('//*[@id="articlelistnew"]/div[@class="articleh normal_post"]/span[3]')
for i in list_text_span:
text = i.xpath('./a/@title')[0]
list_text.append(text)
#print(text)
#爬取评论的时间
list_span = tree.xpath('//*[@id="articlelistnew"]/div[@class="articleh normal_post"]')
for i in list_span:
time = i.xpath('./span[5]/text()')[0]
list_time.append(time)
#print(list_time)
print("第"+str(page)+"爬取完毕")
data = pd.DataFrame()
#print(list_text)
data['pl'] = list_text
data['time'] = list_time
#print(list_time)
#print(data)
#将文件输出保存
data.to_csv('600026.csv',index=False,encoding='utf_8_sig')
三、获取股票近两个月的数据
利用pandas_datareader来获取股票数据,然后计算出涨跌幅,同时将涨跌幅扩大五倍,不然涨跌幅的变化不明显等一下对比不方便,再将数据保存。
代码如下:
import pandas_datareader.data as webdata
import datetime
#生成数据的日期
start_day = datetime.datetime(2020,8,3)
end_day = datetime.datetime(2020,10,16)
#通过yahoo财经查询股票信息(600026)
stock_code = input("输入股票代码,股票代码后面加.sz/.ss:")
stock_info = webdata.get_data_yahoo(stock_code, start_day,end_day)
#计算出涨跌幅并波动扩大五倍,不然波动太小与情绪对比不明显
stock_info['p_change'] = stock_info['Close'].pct_change()*5
#print(stock_info)
#保存数据
stock_info.to_csv('60026.csv',encoding='utf_8_sig')
四、可视化对比
利用snownlp库对评论进行情感分析然后读取股票的涨跌幅,画图进行对比。
代码如下:
import pandas as pd
import matplotlib.pyplot as plt
from snownlp import SnowNLP
#读取数据
orig_comments = pd.read_csv('600026.csv')
#print('原始数据:')
#print(orig_comments.head())
#计算情绪得分
orig_comments['情绪'] = None
lenorig = len(orig_comments)
i = 0
while(i<lenorig):
s = SnowNLP(orig_comments.iloc[i,0]).sentiments
orig_comments.iloc[i,2] = s
i = i+1
#print("情绪得分")
#print(orig_comments.head())
#去掉time后面的时间只保留月日
for i in range(0,lenorig):
orig_comments.iloc[i, 1] = list(orig_comments['time'])[i][0:5]
#print(list(orig_comments['time'])[i][0:5])
#print(orig_comments)
#计算每日的评论平均分
numberByDay = orig_comments['情绪'].groupby(orig_comments['time']).count()
emotionByDay = orig_comments['情绪'].groupby(orig_comments['time']).sum()
markByDay = pd.DataFrame()
markByDay['情绪'] = emotionByDay
markByDay['计数'] = numberByDay
markByDay['情绪平均'] = markByDay['情绪']/markByDay['计数']
#print(markByDay.head())
#将索引转化为日期
markByDay['order'] = markByDay.index
markByDay['日期'] = None
lenMBD = len(markByDay)
i = 0
while(i<lenMBD):
markByDay.iloc[i,4] = '2020-' + markByDay.iloc[i,3]
i = i+1
#print(markByDay)
#读取600026的涨跌幅
zyMarket = pd.read_csv('60026.csv',encoding='utf-8')
#print(zyMarket)
Market = pd.DataFrame()
Market['日期'] = zyMarket['Date']
Market['中远波动'] = zyMarket['p_change']
#print(Market)
#将情绪和涨跌幅的日期设置为索引,将两张表连接起来
markByDay.set_index('日期',inplace=True)
Market.set_index('日期',inplace=True)
result = Market.join(markByDay)
#print(result)
#画图对比
plt.figure(figsize=(10,8))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.plot(result['中远波动'],'r-', label='中远波动',linewidth=3)
plt.plot(result['情绪平均'],'b-', label='情绪波动',linewidth=3)
plt.title('两种波动对比')
plt.xlabel('交易日期', fontsize=20)
plt.ylabel('波动率', fontsize=20)
plt.legend()
plt.show()
结果如下:

image.png
可以发现情绪波动与股票涨跌幅的波动相关。