目的:利用python爬虫爬取豆瓣电影的短评等数据,完成数据的清洗及可视化。
步骤:1、抓取数据;
2、数据处理;
3、数据可视化。
本文会以《楚门的世界》为例,通过爬取短评、评分、时间等数据来进行探索。
首先导入模块
import requests import re,time import pandas as pd from bs4 import BeautifulSoup import csv import codecs # 保存数据 import matplotlib.pyplot as plt from matplotlib import font_manager from pylab import mpl from wordcloud import WordCloud # 词云 import jieba # 分词 import numpy,collections # 词频统计
1、数据的爬取:
def getdata(): header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", "cookie": "_uuid=DB17FC3E-C33B-0402-FEC8-6D5F54FFD75826400infoc; buvid3=524A488F-FA38-4505-A9FD-80539B19E3FB184978infoc; sid=a2zoyf7s; buvid_fp=524A488F-FA38-4505-A9FD-80539B19E3FB184978infoc; DedeUserID=650586683; DedeUserID__ckMd5=673346effe04fe44; SESSDATA=dc4b2c16%2C1628474903%2Cc95da*21; bili_jct=f92980128fe4681476212c6cfe3d0ff7; CURRENT_FNVAL=80; blackside_state=1; rpdid=|(J|)JR|||Rm0J uYukmkkmJk; fingerprint3=dc6c77bb0dfdccdd39bc9efbb780630d; fingerprint=f29725bb59f7984374f945e2ebddc362; buvid_fp_plain=524A488F-FA38-4505-A9FD-80539B19E3FB184978infoc; fingerprint_s=0a7abb581b9ea03451e614a51a3d4b2b; LIVE_BUVID=AUTO8416133069733130; bp_video_offset_650586683=491829482594004200; bsource=search_baidu; PVID=1; bfe_id=1e33d9ad1cb29251013800c68af42315"} original_url = 'https://movie.douban.com/subject/1292064/comments?start=' original_url2 = '&limit=20&status=P&sort=new_score' item = {} temp_list = [] # 爬取豆瓣影评信息,返回response, 并进行解析 for page in range(30): comments = "" url = original_url+ str(page*20) +original_url2 # print(url) resp = requests.get(url, headers=header) soup = BeautifulSoup(resp.text, 'html.parser') # 返回的是class为“main review-item”的所有<div>标签 p_list = soup.find_all('div', {'class': 'comment-item'}) for p_div in p_list: # id id = p_div.get('data-cid') # 短评内容 content = p_div.find('span', {'class': 'short'}).text # 发布时间 pub_time = p_div.find('span', {'class': 'comment-time'}).text.replace('\n','').strip(' ') # 评分(5力荐 4推荐 3还行 2较差 1很差) rating = p_div.find('span', {'class': 'rating'}) # 没有评分的暂空 if rating: rating = rating.get('title') else: rating = "" item = { 'id':id, "pub_time": pub_time, "rating": rating, "content": content, } temp_list.append(item) time.sleep(1) # print(temp_list) # 解决保存乱码的问题 with open("{}.csv".format('ceshi'), "ab+") as file: file.write(codecs.BOM_UTF8) # 保存数据 with open('{}.csv'.format('ceshi'), 'a',newline = "",encoding='utf-8') as file: writer = csv.writer(file) for i in temp_list: info = [i['id'],i['pub_time'],i['rating'],i['content']] writer.writerow(info) resp.close() # DataFrame注意大小写 df = pd.DataFrame(temp_list) return df
2、数据处理
爬取到的数据展示:
def process(): df = getdata() # 没有评分的视为 放弃 df["rating"].fillna("放弃", inplace = True) # 将时间格式改为日期 df['pub_time'] = pd.to_datetime(df['pub_time']) return df
3、数据可视化
(1)时间分布图
def visual_1(): #时间分布图 data = process() # 指定多个时间区间[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24] time_range = list(range(0,25,2)) # 获取评论时间中的hour .dt.hour frame = data['pub_time'].dt.hour # 把一组数据分割成离散的区间,并获取每个区间的评论数 pd.cut() # 第一个参数:被切分的数据,必须是一维的 # 第二个参数:bins:被切割后的区间 # 第三个参数:right:表示是否包含区间右部,默认为True # .value_counts() 给值计数 time_range_counts = pd.cut(frame, bins=time_range, right=False).value_counts() # print('time_range_counts',time_range_counts) # print('time_range_counts.index',time_range_counts.index) # print('time_range_counts.values',time_range_counts.values) # 创建一个画布,并指定宽、高 plt.figure(figsize=(10, 5)) # 字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 绘制柱状图 plt.bar(range(len(time_range_counts.index)), time_range_counts.values, color=['lightskyblue']) # 配置坐标及对应标签 plt.xticks(range(len(time_range_counts.index)), time_range_counts.index) # 设置横轴标签 plt.xlabel('时间区间') # 设置纵轴标签 plt.ylabel('评论人数') # 保存图形 plt.savefig('柱状图.jpg') # 显示图形 plt.show()
(2)评分图
def visual_2(): # 评分饼图 data = process() # 字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False # 按照评分进行聚合 grouped = data['id'].groupby(data['rating']) grouped_count = grouped.count() print(grouped_count) # 图片大小 plt.figure(figsize=(3, 3), dpi=200) # 饼图样式 plt.pie(grouped_count.values, labels=grouped_count.index, autopct='%1.1f%%',pctdistance=0.9, radius=1, counterclock=False, textprops=dict(size=5)) plt.savefig('评分图.jpg') plt.show()
(3)词云图
def visual_3(): # 词云图 data = process() comments = '' for k in range(len(data['content'])): comments = comments + (str(data['content'][k])).strip() # \u4e00、\u9fa5表示中文编码的开始和结束的两个值 filterdata = re.findall('[\u4e00-\u9fa5]', comments) cleaned_data = ''.join(filterdata) # print(cleaned_data) # 文本分词 segment = jieba.lcut(cleaned_data) words_df = pd.DataFrame({'segment': segment}) # 去停用词 stopwords = pd.read_csv("stopwords.txt", index_col=False, quoting=3, sep="\t", names=['stopword'], encoding='utf-8') # quoting=3全不引用 words_df = words_df[~words_df.segment.isin(stopwords.stopword)] # 词频统计 word_counts = collections.Counter(words_df['segment']) # 获取前20最高频的词检查 word_counts_top20 = word_counts.most_common(20) print(word_counts_top20) # 绘制词云图 wc = WordCloud(font_path='C:/Windows/Fonts/simkai.ttf', # 字体 background_color='white', # 背景颜色 width=1200, height=600, max_words=200, # 最大词数 max_font_size=200, # 字体大小 random_state=1234) # 设置多少种随机的配色方案 fig = wc.generate_from_frequencies(word_counts) plt.figure(figsize=(12, 6)) plt.imshow(fig) plt.axis('off') plt.savefig('词云图.jpg', dpi=600) plt.show()
4、数据可视化分析
可以看到:
20:00~24:00时间段评论人数最多,4:00~6:00时间段人数最少。
由此可见,大家都是喜欢选择晚上看电影,而相对不喜欢在凌晨看电影。
可以看到:“力荐”“推荐”的评分人数比例远远高于“放弃”“较差”“还行”,
由此可见,大家都很喜欢《楚门的世界》这部电影,评分很高,推荐观看。
此为词云图。
标签:plt,df,爬取,range,豆瓣,可视化,time,counts,data From: https://www.cnblogs.com/juanmei/p/16977475.html