您的位置:首页 > 编程语言 > Python开发

Python小白逆袭大神(飞桨七天课程)---Day5-综合大作业

2020-05-08 04:19 1251 查看

参加了百度的python七天课程: https://aistudio.baidu.com/aistudio/index
分享一下最后的大作业:
(ps:写作业过程中碰到了add_words问题,参考了叁岁大佬的这篇博文https://blog.csdn.net/weixin_45623093/article/details/105794512)

综合大作业

**第一步:**爱奇艺《青春有你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
# 将字体文件复制到matplotlib字体路径
!cp simhei.ttf /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
# 一般只需要将字体文件复制到系统字体目录下即可,但是在aistudio上该路径没有写权限,所以此方法不能用
# !cp simhei.ttf /usr/share/fonts/

# 创建系统字体文件路径
#!mkdir .fonts
# 复制文件到该路径
!cp simhei.ttf .fonts/
!rm -rf .cache/matplotlib

这里的simhei.ttf需要自己在网上下载,然后上传到当前工作路径下。

#安装模型
!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
#请求爱奇艺评论接口,返回response信息
def getMovieinfo(url):
# '''
# 请求爱奇艺评论接口,返回response信息
# 参数  url: 评论的url
# :return: response信息
# '''
session = requests.Session()
headers = {
"User-Agent":"Mozilla/5.0",
"Accept":"application/json",
"Refer":"http://m.iqiyi.com/v_19rqriflzg.html",
"Origin":"http://m.iqiyi.com",
"Bost":"sns-comment.iqiyi.com",
"Connection":"keep-alive",
"Accept-Language":"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6",
"Aceept-Encoding":"qzip,deflate"
}
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 = "http://sns-comment.iqiyi.com/v3/comment/get_comments.action?agent_type=118&\agent_version=9.11.5&business_type=17&content_id=15068699100&page_size=10&type=time&last_id="
#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&page=&page_size=10&types=time&last_id='
url += str(lastId)
responseTxt = getMovieinfo(url)
responseJson = json.loads(responseTxt)
comments = responseJson['data']['comments']
for val in comments:
if 'content' in val.keys():
print(val['content'])
arr.append(val['content'])
lastId = str(val['id'])
return lastId

注意上面这部分一定要认真检查一下headers和url等的正确性,因为在这里打错是不会报错的,但是之后主函数调用运行的时候会无法爬取评论。之前不小心多打了一个字母,debug了很久才发现是这里的问题(可能是我比较粗心)。

#去除文本中特殊字符
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-9]',"",s)
# s = re.sub('[\001\002\003\004\005\006\007\x08\x09\x0a\x0b\x0c\x0d\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d]','',s)
# s = re.sub('[a-zA-Z]','',s)
# s = re.sub('^\d+(\.\d+)?$','',s)

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-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)
s = re.sub(u'[\U00010000-\U0010ffff]', ' ',s)
s = re.sub(u'[\uD800-\uDBFF][\uDC00-\uDFFF]', ' ', s)
for ch in ',。;:“”、》《、|*&…🙏!♥♡😊🌚?💚√🍼【】💔🐴]๑👍[🌟😘🤘ノ🐱👩‍❤“💎🌸💙😁❄,≧▽≦👀🐶🍬😂 !🧡😃 ヾ↗~↖^ 🏻🍋~♀٩௰^ و˃͈ ̶ω˂😆௰ ˂🔒🧍💛💚💖Ő ∀Ő∀✔🤠( ง _ • 。́ ) ง🔒✨🍑💙💜👧🐛🐟✊🌠🌨💪⭐”…':
s = s.replace(ch, ' ')

return s

上面这段主要是通过正则的方法清除掉爬取的评论中的无用部分。
ps:清除emoji的思路来自同营大佬,这里可以在运行出来之后,看看乱码里面有哪些emoji,然后对应着在这里清除掉。其他无效字符也是同理。

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

return seg

注意,上面的分词文档add_words需要自己自己编写,主要是加入评论中可能出现的高频词,如人气选手姓名等等(可以爬出来评论之后看一下都有哪些高频词,自己手动加一下,毕竟机器模型识别不出来一些人名),注意在加入时每个高频词单独占一行(估计是参数读取方式是按‘\n’读入的原因)。

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

return stopwords
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
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()
def drawcloud(word_f):
'''
根据词频绘制词云图
参数 word_f:统计出的词频结果
return:none
'''
#加载背景图片
cloud_mask = np.array(Image.open('cloud3.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')

这里的cloud.png是一个透明底的背景图,后面词云会根据cloud图里的形状生成,需要自己添加,我是自己p的。

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

'''
pron_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 = pron_detection_lstm.detection(data=input_dict,use_gpu=False, 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 = 200
lastId = '0' #lastId是接口分页id
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')
stopwords = stopwordslist(r'中文停用词表.txt')
movestopwords(words,stopwords,counts)

drawcounts(counts,10)#绘制前十名高频词
drawcloud(counts)#绘制词云
f.close()

#使用hub对评论进行内容分析
file_path = 'aqy.txt'
test_text = []
text_detection(test_text,file_path)

这部分就是主函数了,运行之后可以看到自己爬取的评论内容、数量、还有top10的热词词频图等。下面放一下我运行结果的部分截图。

最后是打印一下词云图片。

display(Image.open('pic.png')) #显示生成的词云图像
syuichihann 原创文章 2获赞 0访问量 122 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: