此次百度飞桨的python+AI的小白基础营,对我个人最大的收获便是在python的学习路上更进了一步步。参加训练营之前,学过C语言,python也大概学了好几个月,但中间中断过很多次,直到这次疫情,又重拾起了python的学习,之前参加过百度飞桨的疫情CV特辑,但只是非常勉强的完成了作业。此次的小白营,将我的学习从python的基础扩展到了爬虫和数据分析,也算是为后续的学习开了一个头。这篇总结心得主要是我对此次大作业的个人分析和总结(其它作业在另一篇博客里),如有错误,还望指正。
第一步:爱奇艺《青春有你2》评论数据爬取(参考链接:https://www.iqiyi.com/v_19ryfkiv8w.html#curid=15068699100_9f9bab7e0d1e30c494622af777f4ba39)
爬取任意一期正片视频下评论
评论条数不少于1000条
第二步:词频统计并可视化展示
数据预处理:清理清洗评论中特殊字符(如:@#¥%、emoji表情符),清洗后结果存储为txt文档
中文分词:添加新增词(如:青你、奥利给、冲鸭),去除停用词(如:哦、因此、不然、也好、但是)
统计top10高频词
可视化展示高频词
第三步:绘制词云
根据词频生成词云
可选项-添加背景图片,根据背景图片轮廓生成词云
第四步:结合PaddleHub,对评论进行内容审核
需要的配置和准备
中文分词需要jieba
词云绘制需要wordcloud
可视化展示中需要的中文字体
网上公开资源中找一个中文停用词表
根据分词结果自己制作新增词表
准备一张词云背景图(附加项,不做要求,可用hub抠图实现)
paddlehub配置
1:打开爱奇艺《青春有你2》的网页,随意选择一期(这里我选的是14期下),翻到评论部分底部, 我们会发现,评论区所对应的源码,在”查看更多评论部分“只有单独的语句,没有展开,同时点击查看更多评论时,评论会直接出现在评论列表中,如果直接爬取,无法满足评论数量要求,只能爬取一面评论。
2:采用NetWork工具分析,可以查看到网页的各部分请求。刷新网页,再次发到评论底部,点击查看更多评论时,会产生一个get_comments请求
查看get_comments请求具体内容,从其preview中可以看到其具体信息,以看到评论内容,ID等信息,据此我们可以认为可以通过此命令来不断爬取评论。
3.查看其Request URL,可以获取评论的JSON信息,我们所爬取和下载的便是通过get_comments请求的URL获取的
4.重新刷新网页,在加载评论的过程中,我们会发现数个get_comments请求,逐一查看其内容,会发现,其last_id属性一直在变化,其它的几乎不变。
5.通过以上分析,我们便可以通过不断改变last_id来获取更多评论,将上一次爬虫得到的last_id作为下一次爬虫的目标
#请求爱奇艺评论接口,返回response信息
'''
请求爱奇艺评论接口,返回response信息
参数 url: 评论的url
:return: response信息
'''
def getMovieinfo(url):
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'
} # 模仿数据请求,防止反爬虫
#爱奇艺第14期下
response = requests.get(url,headers=headers)
return response.text
解析json数据,获取评论
参数 lastId:最后一条评论ID arr:存放文本的list
:return: 新的lastId
'''
#解析json数据,获取评论
def saveMovieInfoToFile(lastId,arr):
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=15535228800&hot_size=0&last_id="
url += str(lastId)
responseTxt = getMovieinfo(url) #获取网页
responseJson = json.loads(responseTxt) #获取网页数据
comments = responseJson['data']['comments'] #获取评论数据(包括id,内容等)
for val in comments:
if 'content' in val.keys(): #防止有val没有'conten'键
con = (val['content']) #具体评论文本
#print(con) #打印评论
arr.append(con) #添加进arr
else:
lastId = str(val["id"])#最后一个id
return lastId
1: 去除文本特殊字符,特殊字符包括中英文标点符号,不可见字符,表情包等,可以通正则表达式处理,表情包的去除,则可以通过专门的emoji库,将表情转化为英文字符后再消除
#去除文本中特殊字符
def clear_special_char(content):
'''
正则处理特殊字符
参数 content:原文本
return: 清除后的文本
'''
s = ''
#将表情符转换成英文字符
s = emoji.demojize(content)
#去除不可见字符
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.findall(r'[\u4e00-\u9fa5]', content)
#重新转换成字符串
s = ''.join(s)
return s
2:利用jieba分词,可以添加自定义词库,格式为
刘雨昕
虞书欣
冲鸭
奥利给
自定义词库可以用来添加一些流行词汇或者人民,增加分词准确性
'''
利用jieba进行分词
参数 text:需要分词的句子或文本
return:分词后的评论列表
'''
def fenci(content):
#jieba.load_userdict("data/add_words.txt") #添加自定义分词典
su = []
for com in content:
seg =jieba.lcut(com,cut_all=False)
for s in seg:
su.append(s)
return su
3.去除停用词,即去除类似于:”于是“,”然后“,”因为“,”所以“之类的词
停用词库:https://github.com/goto456/stopwords
由于停用词库,直接分割会产生换行符,故需要加一个函数用来将停用词库,转化成我们能直接使用分停用词列表,并根据实践效果,添加一些自定义的停用词,如以下代码中的"欣虞书"就是根据运行结果加的。
'''
创建停用词表
参数 file_path:停用词文本路径
return:停用词列表stop
'''
def stopwordslist(file_path):
spc_word = ["欣虞书","真的","言喻",'一个','啊啊啊','镜头','哈哈哈'] #特殊停用词
stop = [] #停用词列表
f1 = open(file_path, "r", encoding="utf-8")
for line in f1.readlines():
line = line.split('\n') # 去除换行符
stop.append(line[0]) # 添加进停用词列表
#print(stop)
for i in spc_word:
stop.append(i) #添加特殊停止词
f1.close()
return stop
在获得可用的停用词库后,直接在评论分词列表中去除,同时利用字典的特性统计词频
'''
去除停用词,统计词频
参数 file_path:停用词文本路径 stopwords:停用词list counts: 词频统计结果
return con #返回的是不带停用词的单词列表
'''
#content:完全净化后的评论词列表
#word_counts:词频字典
#停用词库来源:百度
def movestopwords(file_path,content,word_counts):
con = []
stop = stopwordslist(file_path)
for s in content:
if s in stop:
continue
con.append(s)
for word in con:
if(len(word)!=1): #如果存在就+1,如果不存在就创建
word_counts[word] = word_counts.get(word,0)+1
return con #返回的是不带停用词的单词列表
利用matplotlib库绘制词频统计图
‘’
词频统计图
‘’’
def drawcounts(s,num):
# # 显示matplotlib生成的图形
# % matplotlib inline
x_aixs = []
y_aixs = []
c_order = sorted(s.items(),key=lambda x:x[1],reverse=True) #排序
for c in c_order[:num]:
x_aixs.append(c[0]) #横坐标
y_aixs.append(c[1]) #纵坐标
# 设置显示中文
plt.rcParams[‘font.sans-serif’] = [‘SimHei’] # 指定默认字体
#plt.rcParams[‘axes.unciode_minus’] = False #解决保存图像是负号’-‘显示为方块的问题
plt.bar(x_aixs,y_aixs)
plt.title(’’‘词频统计’’’,fontsize = 24)
plt.savefig(‘bar_result.jpg’)
利用Wordcloud库绘制词云
‘’’
根据词频绘制词云图
参数 word_f:统计出的词频结果
return:none
‘’’
def drawcloud(word_f):
cloud_mask = np.array(Image.open(‘cloud.jpg’)) #加载背景形状,转换成数组形式
ignore = set([]) #忽略词
wc = WordCloud(
background_color = 'white',
mask = cloud_mask, #背景形状
max_words=100, #显示词数
font_path='simhei.ttf',
min_font_size=10, #最小尺寸
max_font_size=100,
width=1200,
relative_scaling=0.3,
stopwords=ignore, #忽略词
mode='RGBA')
wc.fit_words(word_f) #填充词云
wc.to_file('pic.png')
采用PaddleHub的porn_detection_lstm模型
‘’’
使用hub对评论进行内容分析
return:分析结果
‘’’
def text_detection(text):
porn_detection_lstm = hub.Module(name=“porn_detection_lstm”)
input_dict = {“text”:text}
results = porn_detection_lstm.detection(data=input_dict,use_gpu=False,batch_size=1) #训练结果
#print(results)
print(“可能敏感句子:”)
for index,item in enumerate(results):
if item[‘porn_detection_key’] == ‘porn’:
print(item[‘text’],’:’,item[‘porn_probs’])
#评论是多分页的,得多次请求爱奇艺的评论接口才能获取多页评论,有些评论含有表情、特殊字符之类的
#num为爬取
if __name__ == "__main__":
num = 50 #爬取评论数
con = []#含有特殊字符的评论
content = []#不含有特殊字符的评论
count_words={} #词频统计结果
lastId = 41040619521 #初始ID
file_path ="data/baidu_stopwords.txt" #停用词库地址
jieba.load_userdict("data/add_words.txt") #添加自定义分词典
for i in range(0,num): #控制评论数
lastId = saveMovieInfoToFile(lastId,con) #改变了con,即增加了评论内容
time.sleep(0.25) #缓冲
print("共获取{:}条评论".format(len(con)))
# print("净化后的评论:")
for s in con:
s = clear_special_char(s)
if(len(s)==0): #去除空字符串
continue
content.append(s)
content = fenci(content) #分词
content = movestopwords(file_path,content,count_words) #去除停用词,同时统计词频
#print(count_words)
drawcounts(count_words,10)
drawcloud(count_words)
print("词云已完成")
#敏感句子检测
text_detection(con)