数据爬虫、词频统计可视化、词云绘制、语句情感审查——飞桨PaddleHub实战

风格不统一 提交于 2020-05-07 14:51:31

爱奇艺《青春有你2》评论数据爬取,并对评论中的词频进行统计以及对评论进行健康情感审查

随着《青春有你2》的热播,你有没有被那些漂亮的小姐姐吸引呢?作为一个发际线已经到后脑勺的程序员,小姐姐的舞姿、歌声那些都是浮云。你想不想知道每期节目,观众评论最多的内容是什么?评论的内容是否健康呢?通过这篇博客,我将手把手教你如何实现。

需要的配置和准备工作

1、中文分词需要jieba
2、词云绘制需要wordcloud
3、可视化展示中需要的中文字体
4、网上公开资源中找一个中文停用词表
5、根据分词结果自己制作新增词表
6、准备一张词云背景图(必须是白底的图片,可用hub抠图实现)
7、paddlehub配置





pip install jieba
pip install wordcloud
#安装模型
hub install porn_detection_lstm==1.1.0
pip install --upgrade paddlehub

环境配置成功后,可以看到:
在这里插入图片描述

一、到爱奇艺上对评论的内容进行爬取

1、找到我们爬取数据所需要的URL

既然是词频统计,肯定是爬取的越多越好。然而,一个页面加载的评论信息量太少,在爱奇艺的中,怎么找出未加载完的评论呢?在这里告诉你一个能快速找到大量评论的方法:在爱奇艺界面单击右键——>检查——>Notebook
在这里插入图片描述
当我们在爱奇艺页面点击加载更多评论时,在notebook中我们会看到有个get_comments的请求,由于一个网页界面呈现的内容有限,这个请求就是拉取更多内容。
在这里插入图片描述
点开该请求,可以看到:
在这里插入图片描述
其中,Request URL就是我们在爬取数据时所需要的 。通过多次点击加载更多评论,我发现每个get_comments请求中的Request URL只有last_id这个参数在变化,其他都没有变动。所以,我们可以直接用一个循环不停的改动last_id这个参数,就可以一直获取加载的更多评论。





2、导入我们开发需要的模块

from __future__ import print_function
import requests
import json
import re #正则匹配
import time #时间处理模块
import jieba #中文分词
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
from PIL import Image
from wordcloud import WordCloud  #绘制词云模块
import paddlehub as hub

3、评论数据爬取

#请求爱奇艺评论接口,返回response信息
def getMovieinfo(url):
    '''
    请求爱奇艺评论接口,返回response信息
    参数  url: 评论的url
    :return: response信息
    '''
    session = requests.Session()
    headers = {
        "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36",
        "Accept": "application/json",
        "Origin": "http://m.iqiyi.com",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "zh-CN,zh;q=0.9",
        "Connection": "keep-alive",
        "Host": "sns-comment.iqiyi.com",
        "Referer": "https://www.iqiyi.com/v_19ryfkiv8w.html",
    }
    response = session.get(url, headers = headers)
    if response.status_code == 200:
        return response.text

    return None

#解析json数据,获取评论
def saveMovieInfoToFile(lastId, arr):
    '''
    解析json数据,获取评论
    参数  lastId:最后一条评论ID  arr:存放文本的list
    :return: 新的lastId
    '''
    url = "https://sns-comment.iqiyi.com/v3/comment/get_comments.action?agent_type=118&agent_version=9.11.5&authcookie=null&business_type=17&content_id=15068699100&hot_size=0&last_id="
    url += str(lastId) 
    responseTxt = getMovieinfo(url)
    responseJson = json.loads(responseTxt)
    comments = responseJson['data']['comments']
    for val in comments:
        # print(val.keys())
        if 'content' in val.keys():
            # print(val['content'])
            arr.append(val['content'])
        lastId = str(val['id'])
    return lastId

二、对爬取下来的数据进行处理

1、正则化去除评论中的特殊字符、表情等

def clear_special_char(content):
    '''
    正则处理特殊字符
    参数 content:原文本
    return: 清除后的文本
    '''
    s = re.sub(r'</?(.+?)>|$nbsp;|\t|\r', '', content)
    s = re.sub(r'\n', ' ', s)
    s = re.sub(r'\*', '\\*', s)
    s = re.sub('[^\u4e00-\u9fa5^a-z^A-Z^0-0]', '', s)
    s = re.sub('[\001\002\003\004\005\006\007\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19]','',s)
    s = re.sub('[a-zA-Z]', '', s)
    s = re.sub('^\d+(\.\d+)?$','',s)
   
    return s

python 中有一个表情库emoji,也可以通过该库来处理表情字符。在这里我们就直接用正则化来处理。

2、对语句进行分词处理

由于中文语言的特殊性,不同位置进行分词导致语句的语义词义都有很大的差别,我们可以使用Python提供专门的分词库jieba,也可也以自己来定义一个分词规则‘add_words.text’。

def fenci(text):
    '''
    利用jieba进行分词
    参数 text:需要分词的句子或文本
    return:分词结果
    '''
    # jieba.load_userdict('add_words.text')
    seq = jieba.lcut(text, cut_all = False)
    
    return seq

3、创建停用词表

在中文语句中,通常会有一些语气词‘吧、啊、阿、哎、哎呀、哎哟、唉’,转折词等,如果我们不将这种词剔除,将会对我们词频统计产生干扰。

def stopwordslist(file_path):
    '''
    创建停用词表
    参数 file_path:停用词文本路径
    return:停用词list
    '''
    stopwords = [line.strip() for line in open(file_path, encoding='UTF-8').readlines()]
    
    return stopwords

三、统计词频并可视化展示

1、统计词频:

def movestopwords(sentence, stopwords, counts):
    '''
    去除停用词,统计词频
    参数 file_path:停用词文本路径 stopwords:停用词list counts: 词频统计结果
    return:None
    '''
    out = []
    for word in sentence:
        if word not in stopwords:
            if len(word) != 1:
                counts[word] = counts.get(word,0) + 1
    
    return None

2、绘制出词频直方图

def drawcounts(counts, num):
    '''
    绘制词频统计表
    参数 counts: 词频统计结果 num:绘制topN
    return:none
    '''
    x_aixs = []
    y_aixs = []
    c_order = sorted(counts.items(),key=lambda x:x[1],reverse=True)
    for c in c_order[:num]:
        x_aixs.append(c[0])
        y_aixs.append(c[1])
    matplotlib.rcParams['font.sans-serif'] = ['SimHei']
    matplotlib.rcParams['axes.unicode_minus'] = False
    plt.bar(x_aixs,y_aixs)
    plt.title('词频统计结果')
    plt.show()
    

3、绘制词云图

def drawcloud(word_f):
    '''
    根据词频绘制词云图
    参数 word_f:统计出的词频结果
    return:none
    '''
    cloud_mask = np.array(Image.open('cloud.png'))
    #忽略显示的词
    st = set(['东西‘, ‘这是'])
    #生成wordcloud对象
    wc = WordCloud(background_color = 'white',
    # mask = cloud_mask,
    max_words = 150,
    font_path='./fonts/simhei.ttf',
    min_font_size = 10,
    max_font_size = 100,
    width = 400,
    relative_scaling = 0.3,
    stopwords = st)
    wc.fit_words(word_f)
    wc.to_file('pic.png')

cloud.png为词云背景图,背景色为白色的一张图片:在这里插入图片描述

四、对评论内容进行健康分析

这里主要用百度飞桨的porn_detection_lstm模型,进行情感的判断。

def text_detection(text,file_path):
    '''
    使用hub对评论进行内容分析
    return:分析结果

    '''
    porn_detection_lstm = hub.Module(name='porn_detection_lstm')
    f = open('aqy.txt','r',encoding='utf-8')
    for line in f:
        if len(line.strip()) == 1:
            continue
        else:
            test_text.append(line)
    f.close()
    input_dict = {'text':test_text}
    results = porn_detection_lstm.detection(data=input_dict,use_gpu=True,batch_size = 1)
    for index, item in enumerate(results):
        if item['porn_detection_key'] == 'porn':
            print(item['text'],':',item['porn_probs'])

五 、最终结果

#评论是多分页的,得多次请求爱奇艺的评论接口才能获取多页评论,有些评论含有表情、特殊字符之类的
#num 是页数,一页10条评论,假如爬取1000条评论,设置num=100
if __name__ == "__main__":
    num = 60
    lastId = 0
    arr = []
    with open('aqy.txt','a',encoding='utf-8') as f:
        for i in range(num):
            lastId = saveMovieInfoToFile(lastId, arr)
            time.sleep(0.5)
        for item in arr:
            Item = clear_special_char(item)
            if Item.strip()!='':
                try:
                    f.write(Item+'\n')
                except Exception as e:
                    print('含有特殊字符')
    print('共爬取评论:',len(arr))
    f = open('aqy.txt','r',encoding='utf-8')
    counts = {}
    for line in f:
        words = fenci(line)
        stopwords = stopwordslist('cn_stopwords.txt')
        movestopwords(words,stopwords,counts)
    # print(counts)
    drawcounts(counts,10)
    drawcloud(counts)
    f.close()

    file_path = 'aqy.txt'
    test_text= []
    text_detection(test_text,file_path)

这里的num控制爬取数据的循环次数,在这里num=60,我们大概可以爬取1700多条评论数据。

1、词频直方图结果展示:

在这里插入图片描述

2、词云展示:

在这里插入图片描述

3、健康情感分析结果,可用于内容审查

在这里插入图片描述

在这里插入图片描述
可以看出,当评论为“色色色”之类的时,不健康指数很高。
至此,整个过程已经结束。

六、说明

主函数中:

........
stopwords = stopwordslist('cn_stopwords.txt')
........
 file_path = 'aqy.txt'

需要自己提供的文件:
cn_stopwords.txt为停用词表,我们可以根据常见的停用词进行原文本停用词的剔除;aqy.txt为进行健康审查时的评论文本。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!