爱奇艺评论爬虫、词频统计、词云、PaddleHub内容审核

需求

第一步:爱奇艺《青春有你2》评论数据爬取(参考链接:https://www.iqiyi.com/v_19ryfkiv8w.html#curid=15068699100_9f9bab7e0d1e30c494622af777f4ba39)

  • 爬取任意一期正片视频下评论
  • 评论条数不少于1000条

第二步:词频统计并可视化展示

  • 数据预处理:清理清洗评论中特殊字符(如:@#¥%、emoji表情符),清洗后结果存储为txt文档
  • 中文分词:添加新增词(如:青你、奥利给、冲鸭),去除停用词(如:哦、因此、不然、也好、但是)
  • 统计top10高频词
  • 可视化展示高频词

第三步:绘制词云

  • 根据词频生成词云
  • 可选项-添加背景图片,根据背景图片轮廓生成词云

第四步:结合PaddleHub,对评论进行内容审核

需要的配置和准备

  • 中文分词需要jieba
  • 词云绘制需要wordcloud
  • 可视化展示中需要的中文字体
  • 网上公开资源中找一个中文停用词表
  • 根据分词结果自己制作新增词表
  • 准备一张词云背景图(附加项,不做要求,可用hub抠图实现)
  • paddlehub配置
!pip install jieba
!pip install wordcloud

# Linux系统默认字体文件路径
!ls /usr/share/fonts/
# 查看系统可用的ttf格式中文字体
!fc-list :lang=zh | grep ".ttf"

 !wget https://mydueros.cdn.bcebos.com/font/simhei.ttf
 !mkdir .fonts
 # 复制字体文件到该路径
 !cp fonts/simhei.ttf .fonts/

#!cp fonts/simhei.ttf /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
#!rm -rf .cache/matplotlib

#安装模型
!hub install porn_detection_lstm==1.1.0
!pip install --upgrade paddlehub
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
import os, sys

#请求爱奇艺评论接口,返回response信息
def getMovieinfo(url):
    '''
    请求爱奇艺评论接口,返回response信息
    参数  url: 评论的url
    :return: response信息
    '''

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
  
    try:
        response = requests.get(url, headers=headers)
        if response.status_code==200:
            return json.loads(response.text)
        else:
            return None
      
    except Exception as e:
        print(e)

    return None

#解析json数据,获取评论
def saveMovieInfoToFile(lastId,arr):
    '''
    解析json数据,获取评论
    参数  lastId:最后一条评论ID  arr:存放文本的list
    :return: 新的lastId
    '''
    # &callback=jsonp_1587899511324_59086
    url = 'https://sns-comment.iqiyi.com/v3/comment/get_comments.action?agent_type=118&agent_version=9.11.5&authcookie=a3fFx3Pr964sHm1rgm3RbWjyKIeM04eCWEOpxPs2pHLam1Oeom2Nqc9R1r1cHrF57ydg9a56&business_type=17&content_id=15068699100&hot_size=10&last_id='+lastId+'&page=&page_size=40&types=hot,time'
    content=getMovieinfo(url)
    
    # start_index=content.find('''{"data"''');
    # data=json.loads(content[start_index:-14]);
      # print(len(comment_list))

   
    comment_list=content['data']['comments']
    for comment in comment_list:
         if 'content' in comment.keys():
             arr.append(comment['content'])
         lastId=comment['id']
    
    #递归
    if len(arr) < 1100 :
        time.sleep(0.5)
        saveMovieInfoToFile(lastId,arr)
    else:
        return 

注意爱奇艺评论页面,此次不是直接在html获取数据,而且F12-network中找到评论接口,然后分析参数,再进行爬。获取下一页的逻辑是 每次把上一页最后一条数据的lastId给带上。

#去除文本中特殊字符
def clear_special_char(content):
    '''
    正则处理特殊字符
    参数 content:原文本
    return: 清除后的文本
    '''
    s = re.sub(r"| |\t|\r", "", content)
    s = re.sub(r"\n"," ",s)
    s = re.sub(r"\*", "\\*", s)
    s = re.sub('[^\u4e00-\u9fa5^a-z^A-Z^0-9]',"",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\x1a]+", "",s)
    s = re.sub('[a-zA-Z]','',s)
    s = re.sub('^\d+(\.\d+)?$',"",s)
    return s

def fenci(dictPath,text):
    '''
    利用jieba进行分词
    参数 text:需要分词的句子或文本
    return:分词结果
    '''
    jieba.load_userdict(dictPath) #添加自定义字典
    seg = jieba.lcut(text, cut_all=False)
    return seg


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

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

    
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)
    # print(c_order)
    for c in c_order[:num]:
        x_aixs.append(c[0])
        y_aixs.append(c[1])

    
    #解决中文显示问题
    plt.rcParams['font.family'] = ['sans-serif']
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
    plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题

    plt.bar(x_aixs, y_aixs)
    plt.title( "词频统计结果")
    plt.show()

def drawcloud(content):
  
    aimask=np.array(Image.open("ai2.png"))

    wc = WordCloud(font_path='fonts/simhei.ttf',  # 设置字体
               background_color="white",  # 背景颜色
               max_words=1000,  # 词云显示的最大词数
               max_font_size=50,  # 字体最大值
               min_font_size=10, #字体最小值
               random_state=42, #随机数
               mask=aimask,
               margin=10,
               collocations=False, #避免重复单词
              )
  
    # print(str(content))
    wc.generate(str(content))  
    plt.figure(dpi=200) #通过这里可以放大或缩小
    plt.imshow(wc, interpolation='bilinear')
    plt.axis("off") #隐藏坐标
    plt.show()

或者如下配置------------------------------------------

  '''
    根据词频绘制词云图
    参数 word_f:统计出的词频结果
    return:none
    '''
    #加载背景图片
    cloud_mask = np.array(Image.open('cluod.png'))
    #忽略显示的词
    st=set(["东西","这是"])
    #生成wordcloud对象
    wc = WordCloud(background_color='white', 
    mask=cloud_mask,
    max_words=150,
    font_path='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')

    '''
    根据词频绘制词云图
    参数 word_f:统计出的词频结果
    return:none
    '''
def text_detection(test_text, path):
    porn_detection_lstm = hub.Module(name="porn_detection_lstm")
    f = open(path, 'r', encoding='utf-8')
    for line in f:
        if len(line.strip()) == 1:  # 判断评论长度是否为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':
            if item['porn_probs']>0.9:
                print(item['text'], ':', item['porn_probs'])

    '''
    使用hub对评论进行内容分析
    return:分析结果

    '''


#评论是多分页的,得多次请求爱奇艺的评论接口才能获取多页评论,有些评论含有表情、特殊字符之类的
#num 是页数,一页10条评论,假如爬取1000条评论,设置num=100
if __name__ == "__main__":

    filePath='data/iqiyi.txt'
    fenciAddDictPath='fenci_add_dict.txt' 
    fenciForbidDictPath='fenci_forbid_dict.txt' 

#【1】第一步:通过“递归”爱奇艺《青春有你2》
#爬取任意一期正片视频下评论
#评论条数不少于1000条


arr=[]
print('评论抓取中')
saveMovieInfoToFile('',arr)
print('爬取评论数量为%d'%len(arr))

#【2】词频统计并可视化展示
# 数据预处理:清理清洗评论中特殊字符(如:@#¥%、emoji表情符),清洗后结果存储为txt文档
    
if os.path.exists(filePath):
    os.remove(filePath)
with open(filePath,'a',encoding='utf-8') as f:
    #遍历清洗评论
    for txt in arr:
        text=clear_special_char(txt)
        if(text.strip()!=''):
            try:
                f.write(text+'\n')
            except Exception as e:
                print("find exception",e)
 

f=open(filePath,'r',encoding='utf-8')
# 统计top10高频词
counts={}
for line in f:
# 中文分词:添加新增词(如:青你、奥利给、冲鸭),去除停用词(如:哦、因此、不然、也好、但是)
    words = fenci(fenciAddDictPath,line)  
    stopwords = stopwordslist(fenciForbidDictPath)
    movestopwords (words ,stopwords,counts)
    
# 可视化展示高频词
drawcounts(counts,10) #绘制top10 高频词
        
    

# 【3】绘制词云
# 根据词频生成词云
# 可选项-添加背景图片,根据背景图片轮廓生成词云

drawcloud(counts) #绘制词云
f.close( )

# 【4】结合PaddleHub,对评论进行内容审核
test_text =[]
text_detection(test_text,filePath)


爱奇艺评论爬虫、词频统计、词云、PaddleHub内容审核_第1张图片
爱奇艺评论爬虫、词频统计、词云、PaddleHub内容审核_第2张图片
爱奇艺评论爬虫、词频统计、词云、PaddleHub内容审核_第3张图片

你可能感兴趣的:(人工智能)