金融科技之情感分析:股民情绪指数与股市价格的相关性分析 |
您所在的位置:网站首页 › 爬取评论数据 › 金融科技之情感分析:股民情绪指数与股市价格的相关性分析 |
金融科技之情感分析(一):股民情绪指数与股市价格的相关性分析
源代码获取前言文本数据源介绍评论数据爬取数据存储和查询计算情绪指数股票历史价格数据的获取相关性分析和可视化
源代码获取
2020年11月11日: 源代码可在点赞、评论该博文后,在下面百度网盘中自行下载。 复制这段内容后打开百度网盘App,操作更方便哦。 链接:https://pan.baidu.com/s/1Tzg-gdC6_-hvm1_b189aeA 提取码:9wx6 前言本文是我在一家金融机构实习时做的第一个项目的整理。蒟蒻一枚,是金融科技和人工智能的初学者,写下本篇博文意在记录自己的足迹并与和我一样想要从事金融科技行业的小伙伴分享我遇到的问题和解决方案。如果本文有错误的地方,请大佬们指正。 在投资者社区中有许多文本型数据,我们可以对这些文本型数据进行处理,挖掘出有价值的信息。比如,东方财富股吧中有很多用户的发言、评论,我们可以借助自然语言处理中的情感分析技术,挖掘出市场的情绪指数,并研究情绪指数与金融市场的相关性。这个项目做的就是这个工作。 主要涉及爬虫、自然语言处理和相关性分析以及有限的MySQL的技术。 文本数据源介绍首先我们打开http://guba.eastmoney.com/list,zssh000001,f.html,进入上证指数吧。进入后的界面如下图所示,同时我们选择排序方式为“发帖时间”。 我们通过分析数据源——股吧,发现我们所需要的数据基本上都被包含在了相关页面的HTML源代码中。那下一步便可以设计我们的爬虫了。我们这里只使用requests和BeautifulSoup两个库便可以完成数据爬取的任务了。 首先,引入这两个库。若还未安装这两个库,只需通过pip安装即可。 import requests from bs4 import BeautifulSoup首先把requests进一步封装成根据url获取HTML的函数 def getHtml(url):#下载网页源代码 header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; LCTE; rv:11.0) like Gecko'} try: r=requests.get(url,headers=header) r.encoding='utf-8' #print(r.status_code) r.raise_for_status() return r.text except: getHtml(url)现在我们可以根据url地址获取对应网页的HTML源代码。下一面要做的便是解析HTML的结果,定位我们需要的数据的位置。 通过分析股吧页面的HTML源代码我们发现,每条评论、公告、新闻等数据都存储在一个div标签下,且该div标签的class属性为articleh。 通过上面的代码段,我们已经从股票的评论列表页面中获取了我们需要的数据。下面我们将根据我们获取的conteUrl和userUrl获取其他我们需要的信息,方法和上面类似。 commentHtml=getHtml(contentUrl)#获取评论详细信息源代码 soup = BeautifulSoup(commentHtml, "html.parser") date = soup.find("div", {"class": "zwfbtime"}).text[4:14]#获取评论发表时间 likeCount=int(soup.find("div", {"data-like_count": True}))#获取评论点赞数,并转换成整数类型。(因为从html中获取会认为是字符串类型) userHtml=getHtml(userUrl)#获取用户主页源代码 soup = BeautifulSoup(userHtml, "html.parser") fans=int(soup.find("a", {"id": "tafansa"}).find("span").text)#获取用户粉丝数至此,我们已经能够获取我们所需要的数据了。但目前我们只是从评论列表的第一页获取数据,如果获取其他页的数据呢?很简单,当我们在网页上点击第二页时,可以发现浏览器的地址栏变成了 http://guba.eastmoney.com/list,zssh000001,f_2.html。所有我们只需要改变该地址字符串的”f_2”和“.html“之间的数字即可。 不过,上述代码只是简化后的结果。没有考虑如果该条”评论“是新闻、讨论、问答等的情况。事实上,这些情况经常出现,且因为不同类型的数据其html得到标签结构往往不同,所有可能导致程序异常终止。一个简单粗暴的方法便是在程序段外面,在循环语句下加上try-except异常处理,若出现异常,则执行continue语句,跳过这一层循环,即跳过该条”评论“。 html=getHtml(url) soup = BeautifulSoup(html, "html.parser") contain = soup.find_all("div", {"class": "articleh"}) for i in contain: try: content=i.find("span", {"class": "l3 a3"}).find("a") contentUrl="http://guba.eastmoney.com"+content["href"] commentId=content["href"][-14:-5] text=content.attrs["title"] userUrl=i.find("span", {"class": "l4 a4"}).find("a").attrs["href"] userId=userUrl[23:] commentHtml=getHtml(contentUrl) soup=BeautifulSoup(commentHtml, "html.parser") date=soup.find("div", {"class": "zwfbtime"}).text[4:14] likeCount=int(soup.find("div", {"data-like_count": True}) userHtml=getHtml(userUrl) soup=BeautifulSoup(userHtml, "html.parser") fans=int(soup.find("a", {"id": "tafansa"}).find("span").text) except: continue这样可以解决大多数情况的问题,但也并非万无一失。可能有的”评论“标签(这里指新闻讨等类型的数据)执行try语句下的代码并没有出现异常,但存储的数据并非我们想要的内容。这需要我们在实践的过程中不断总结、寻找规律、判断并排除这类情况。 至此,获取数据我们已经介绍完了。 数据存储和查询在利用爬虫技术获取到我们需要的数据后,便需要将数据存储以待后续处理。数据存储有很多方法,在这里,我们将其存储到数据库中。 这里使用的是MySQL数据库和DataGrip数据库图形界面操作工具。读者可参考网络上的MySQL安装教材进行安装。若读者无法使用DataGrip(收费软件,在校大学生和教师可申请免费使用)也无妨,我只是使用该软件方面查看数据库的内容。 成功安装数据库,并输入密码登录后。便可以创建数据库和数据表了。 首先我们创建数据库。注:windows操作系统下不区分大小写 create database dfcf;其中,dfcf是自定义的数据库名。dfcf即东方财富。 接着,我们在dfcf数据库中创建数据表。 use dfcf; create table tb_comment ( id int auto_increment primary key, comment_id varchar(20) null, content varchar(300) null, like_count int null, date date null, user_id varchar(20) null, share_code varchar(15) null, ); create table tb_user ( id char(18) not null primary key, fans int null );通过上面的代码,我们便在dfcf数据库中创建了两个表。一个存储评论的相关信息,另一个存储用户的相关信息。在tb_comment表中,id字段为从1开始递增的整数,用来方便查看存储的数据总数。share_code字段存储的是该条评论所针对的股票,在这里,因为我们研究的是上证指数吧,所以share_code为zssh000001. 现在我们已经打建好了数据库。下一个问题便是如何向数据库中存储和从数据库中查询数据了。只需要简单的了解一下SQL语句即可。对数据库的操作基本上可以归为增删改查四大块。每一块常用的语句很少也很简单,读者自行在网络上了解即可,后面我也会给出用到的SQL语句。 关于数据存储和查询的最后一个问题便是:如何使用Python对数据库进行操作。 事实上,我们只需要安装pymysql库,再按照一定格式调用即可。下面给出例子: import pymysql def storeCommentInf(comment):#存储评论 db = pymysql.connect("localhost", "root", "你的登录密码", "dfcf") cur=db.cursor() sql = "INSERT INTO TB_COMMENT(comment_id,content,like_count,date ,user_id,share_code) values (%(comment_id)s,%(content)s,%(like_count)s,%(date)s,%(user_id)s,%(share_code)s)" sql1 = "SELECT * FROM TB_COMMENT where COMMENT_ID=%s" if cur.execute(sql1,(comment["comment_id"])):#去重 cur.close() print("评论已经存在") db.close() else: cur.execute(sql, (comment)) db.commit() cur.close() db.close() print("插入评论成功")在上面的代码中,我们首先导入了pymysql库,并定义了一个函数。函数中有一个参数comment,为字典类型,存储的是一条评论的有关数据。上述代码段的第3行,我们连接了dfcf数据库。第4行,我们引入了一个会话指针,这是固定写法,读者不必深究。随后,我们定义个两个字符串sql和sql1来定义要执行的数据库操作。sql用来插入comment,其values()内定义的%(xxx)s中的”xxx"是参数comment中的键,执行该语句可以将参数comment对应键的值存入数据库对应字段中。sql1用来根据comment_id来查询数据,避免同一条评论被重复插入。cur.execute()便是用来执行设置好的sql语句。 下面给出全部的用到的关于数据库操作的函数: import pymysql def storeCommentInf(comment):#存储评论 db = pymysql.connect("localhost", "root", "你的登录密码", "dfcf") cur=db.cursor() sql = "INSERT INTO TB_COMMENT(comment_id,content,like_count,date ,user_id,share_code) values (%(comment_id)s,%(content)s,%(like_count)s,%(date)s,%(user_id)s,%(share_code)s)" sql1 = "SELECT * FROM TB_COMMENT where COMMENT_ID=%s" if cur.execute(sql1,(comment["comment_id"])):#去重 cur.close() print("评论已经存在") db.close() else: cur.execute(sql, (comment)) db.commit() cur.close() db.close() print("插入评论成功") def storeUserInf(user):#储存用户数据 db = pymysql.connect("localhost", "root", "你的登录密码 ", "dfcf") cur = db.cursor() sql = "INSERT INTO TB_USER(id,fans) values (%(id)s,%(fans)s)" sql1="SELECT * FROM TB_USER where ID=%s" if cur.execute(sql1,(user["id"])):#去重 cur.close() db.close() print("用户已经存在") else: cur.execute(sql, (user)) db.commit() cur.close() db.close() print("插入用户成功") def selectCommentOrderByDate(share_code,method):#查询评论信息 db = pymysql.connect("localhost", "root", "你的登录密码", "dfcf") cur = db.cursor() if method==0:#按照日期升序 sql = "SELECT * FROM TB_COMMENT WHERE SHARE_CODE=%s ORDER BY DATE" else:#按照日期降序 sql="SELECT * FROM TB_COMMENT WHERE SHARE_CODE=%s ORDER BY DATE DESC " cur.execute(sql,(share_code)) db.commit() cur.close() return cur.fetchall() def selectFansByUserId(userId):#查询用户粉丝数 db = pymysql.connect("localhost", "root", "你的登录密码", "dfcf") cur = db.cursor() sql = "SELECT FANS FROM TB_USER where ID=%s" cur.execute(sql,userId) db.commit() cur.close() return cur.fetchall()至此,我们已经解决了获取数据和存储、查询数据的问题了。 计算情绪指数现在,我们便可以计算投资者的情绪指数了。我们需要借助自然语言处理中的情感分类技术。按照正常的处理流程,我们需要搭建模型、准备语料库、训练模型、测试模型然后得到一个情感分类的模型。但这里,我们直接使用现有的模型。snownlp是一个中文的开源的自然语言处理的Python库,可以进行分词、情感分类等。但snownlp库有一个缺陷,便是其模型的训练语料是商品购物评论语料,用来做金融领域的情感分类效果一般,但目前还并没有关于金融领域的中文自然语言处理的开源库、语料库。所以这里我们暂时使用snownlp库来完成我们的实验。若想进一步提高准确率,还需自己搭建语料库进行模型训练。 下面介绍用snownlp进行情感分析的方法: 首先,需要安装snownlp库,直接用pip安装即可。安装完毕之后,按照下列方法调用。 from snownlp import SnowNLP text="大牛市来啦,发财啦" nlp=SnowNLP(text) print(nlp.sentiments)运行上述代码,我们可以得到一个浮点数0.7343040563996935。nlp.sentiments是一个在【0,1】之间的浮点数,这个数越接近1,代表该文本表达的积极情绪越强,反之,则代表该文本表达的消极情绪越强。 现在我们已经可以计算一个评论文本的情感得分了,下一步便是量化出某一日市场投资者的整体情绪。量化的方法有许多种,可以将某一日所有的评论情绪得分得分相加再求评价,也可以求某一日情绪得分大于0.5的评论所占的比例。 本蒟蒻采用的方法是: ①将情绪得分>0.6的评论当作积极评论,小于0.4的评论当作消极评论。 ②设置变量neg和pos,存储某一日市场的积极情绪因子和消极情绪因子。关于neg和pos的计算方法,以neg为例: 初始化为0 若某一日的某一评论comment的情绪得分0.6): fans=SQL.selectFansByUserId(comment['user_id']) pos+=1+math.log(comment['like_count']+fans[0][0]+1,2) if(sentimentScore |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |