微博评论情感分析-百度自然语言处理API使用教程

最近在做微博的评论情感分析,本来想用Tensorflow的RNN来实现,但网上一直找不到好的训练集,在CSDN上买的几万条的微博情感标注集效果也不好,模型对训练集的准确率很高,但放到实际预测中效果很差。

在暂时没有时间自己做标注的情况下,只能先考虑一些现有的工具了,之前用过百度AI的自然语言处理,凑合能用,个人感觉他们的训练集应该量是比较大的,能适应的场景比较多。实际使用后还没有发现很离谱的打标打错的情况,所以记录一下供大家参考,使用的是Python3.6+Requests库。

准备工作

首先要先在百度AI控制台申请一下应用。

创建应用

创建应用后保存自己的API key和Secret key,要用到这两个字段去获取AccessToken,然后再用AccessToken访问API。

应用管理

获取AccessToken

虽然百度API的技术文档里有介绍,但用的是python2.7版本的,而且是urllib库。转换成Requests库更方便,代码如下:

# 获取AccessToken类
class GetAccessToken:
    def __init__(self):
        # 【修改点1】输入自己在百度AI控制台申请应用后获得的AK和SK
        self.AK = ''
        self.SK = ''
        self.token_url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id='+self.AK+'&client_secret='+self.SK
        self.headers = {'Content-Type':'application/json; charset=UTF-8'}

    def get_access_token(self):
        r = requests.get(self.token_url,headers = self.headers)
        if r.text:
            tokenkey = json.loads(r.text)['access_token']
            print('get token success')
            return tokenkey
        else:
            print('get token fail')
            return ''

将之前申请的API key和Secret key填入字段即可获得AccessToken。

调用API接口

由于是穷人,只能使用普通权限,QPS限制为5,也就是最多这个接口每秒能处理5次请求,超过就会返回错误。但实际的请求速度还是跟网速和电脑配置有关,比如设置了每个0.1秒请求一次,但实际发送请求时有时候是0.1S发送,有时候是0.3S发送,但如果连续多次0.1S发送请求就会报错,因此在调用时考虑每次出现错误就增加一点等待时间,而一段时间没有报错就减少一点等待时间,保持自己能最大化利用免费接口的请求量(这就是穷人的心机吗...)。代码解释见注释,直接使用需修改两个地方1.更改待分析文本所在文件夹地址;2.根据自己文本的格式,修改读取文件的方式

# 调用API类
class SentimentBaidu:
    def __init__(self,tp):
        # 调用自己需要使用的API,这里使用情感分析API作为示例,其他接口查询百度AI说明文档后替换 + 前的URL
        self.HOST = 'https://aip.baidubce.com/rpc/2.0/nlp/v1/sentiment_classify' + '?charset=UTF-8&access_token='
        self.headers = {'Content-Type': 'application/json','Connection': 'close'}
        self.textpath = tp
        self.commentcomment = []
        self.count = 0
        # 速度设置,对应百度AI的QPS限制,由于request发送请求的速度跟网速、设备性能有关,所以虽然限制是5QPS,但可以把请求的间隔写短点,这里采用的是最快0.06s
        self.speedlimit = 0.06
        # 初始速度,后续实际请求速度程序自动根据错误调整
        self.sleepdt = 0.08
        self.errorwaittime = 0.5
        self.qpserror = 0
        self.qpserrorindex = 0
        self.errorallcount = 0
    
    # 调用百度API获得情感分析结果方法
    def get_content_sentiments(self,text,at):
        raw = {'text': text}
        data = json.dumps(raw).encode('gbk')
        url = self.HOST+at
        try:
            if self.count - self.qpserrorindex > 500:
                if self.sleepdt > self.speedlimit:
                    self.sleepdt -= 0.001
                    print('speed up, current speed:',
                          self.sleepdt)
                    self.qpserrorindex = self.count
            time.sleep(self.sleepdt)
            r = requests.post(url=url, data=data, headers=self.headers)
            if 'error_code' in r.text:
                error = r.json()['error_code']
                print('error_code',error)
                if error == 18:
                    self.errorallcount += 1
                    self.qpserror += 1
                    self.qpserrorindex = self.count
                    self.sleepdt += 0.001
                    print('current qps error count = ', self.qpserror, 'speed down, current speed:', self.sleepdt, self.errorallcount)
                    time.sleep(self.errorwaittime)
            content = r.json()
        except Exception as e:
            self.errorallcount += 1
            time.sleep(self.errorwaittime)
            return
        try:
            if content['items']:
                contentposprob = content['items'][0]['positive_prob']
                contentnegprob = content['items'][0]['negative_prob']
                contentconfi = content['items'][0]['confidence']
                contentsenti = content['items'][0]['sentiment']
                temp = [contentposprob,contentnegprob,contentconfi,contentsenti]
                return temp
        except KeyError as e:
            self.errorallcount += 1
            print('error reason:',content)
            time.sleep(self.errorwaittime)
            return
    
    # 使用pandas读取所有待分析文本
    def get_comment_ori(self,fp):
        fpath = fp
        fpl = os.listdir(fpath)
        contentall = []
        for file in fpl:
            fd = fpath + '/' + file
            print('reading',fd)
            temp = pd.read_csv(fd)
            contentall.append(temp)
        contentalldf = pd.concat(contentall, ignore_index=True, sort=False)
        print('comment get:',contentalldf.shape[0])
        return contentalldf

    # 主程序
    def run(self):
        requests.adapters.DEFAULT_RETRIES = 5
        ATclass = GetAccessToken()
        AT = ATclass.get_access_token()
        print('progress start current speed = ', self.sleepdt)
        # 【修改点3】以下4行为获取文本,可选择自己常用的方式,将所有文本待分析文本放到一个iterator中,这里使用的pandas读取文本
        contentalldf = self.get_comment_ori(self.textpath)
        commentcontent = contentalldf['commentContent']
        commentcontent = pd.DataFrame(commentcontent)
        commentcontent.columns = ['comment']
        # 如果在调用接口前想先对文本符号、表情等信息进行清理,可调用clean_comment函数,通过pandas的apply快速处理所有文本
        # commentcontent['comment'] = commentcontent['comment'].apply(self.clean_comment)
        for comment in commentcontent['comment']:
            if comment:
                self.count += 1
                if self.count % 100 == 0:
                    print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time())),'正在处理第{0}条评论'.format(self.count))
                commentsenti = self.get_content_sentiments(comment,AT)
                if commentsenti is not None:
                    commentbatch = [comment]+commentsenti
                    self.commentcomment.append(commentbatch)
                if self.count % 100 == 0:
                    commentsentidf = pd.DataFrame(self.commentcomment,
                                                  columns=['comment', 'contentposprob', 'contentnegprob',
                                                           'contentconfi', 'contentsenti'])
                    fpath = self.textpath + '/cpbaidu.csv'
                    if os.path.exists(fpath):
                        commentsentidf.to_csv(fpath, mode='a', encoding='utf-8-sig', index=False, header=False)
                    else:
                        commentsentidf.to_csv(fpath, encoding='utf-8-sig', index=False)
                    # print('write to path',fpath,'write num:',commentsentidf.shape[0])
                    self.commentcomment = []
        print('finished progress')
    
    # 文本清理方法,可选是否剔除文本内的符号、空格、emoji的剔除
    def clean_comment(self,text):
        emoji = re.compile(u'['
                          u'\U0001F300-\U0001F64F'
                          u'\U0001F680-\U0001F6FF'
                          u'\u2600-\u2B55]+',
                          re.UNICODE)
        text = re.sub("[\s+\.\!\/_,$%^*(+\"\']+|[+——!,。?、~@#¥%……&*()::]+", "", text)
        text = re.sub(emoji,'',text)
        return text


if __name__=='__main__':
    tp = '' # 【修改点2】修改为自己的文本存储的文件夹位置
    runner = SentimentBaidu(tp)
    runner.run()

调用效果

实际效果打标结果只能说勉强能用,而且由于之前没有做停用词去除,所以很多微博名字也被放到文本中进行分析了,所以最好在将文本提交API之前先对文本进行清理,去掉停用词和符号等内容,另外如果纯表情的微博回复调用接口会直接报空,也可以提前清除。打标结果如下,后面字段分别为,积极概率,消极概率,判断信心,情感分类(0消极 1中性 2积极)

打标效果

 

完整项目见:https://github.com/pandasgb/SentimentAnalysisWithBaiduAI

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值