- 1 前言
- 2 项目介绍
- 3 效果展示
- 4 项目分析
- 4.1 爬虫部分
- 4.2 数据分析部分
- 5 最后-毕设帮助
Hi,大家好,这里是丹成学长,今天做一个电商销售预测分析,这只是一个demo,尝试对电影数据进行分析,并可视化系统
毕设帮助,开题指导,技术解答
🇶746876041
2 项目介绍
首先通过网页开发者工具分析豆瓣电影网站,然后使用抓包工具拦截数据,从中找出api接口,接下来使用Python爬虫进行数据的下载。数据下载完后,使用pandas模块处理csv电影数据文件,之后可以选用各种数据分析的方法对数据进行挖掘,包括但不限于关键词提炼、词频统计、相关性探索、电影分类,再通过matplotlib绘制数据统计图如条形图、饼状图,亦或是wordCloud绘制评论词云。
3 效果展示
豆瓣电影官网虽然没有令人窒息的反爬 *** 作,但是接口较为隐蔽,需要通过Fiddler抓包工具辅助,才能找到电影数据接口。
编写爬虫时使用xpath对网页数据进行提取,使用正则表达式过滤冗余文本数据并对文本进行清洗。爬虫运行过程中要控制爬取速度,否则在运行时不会出现爬取问题,但经过一段时间后豆瓣官网检测到本台主机IP的不正常请求,就会对IP进行封锁,阻止下一次大规模爬取。
通过登录豆瓣账号获得Cookie可以减缓这一点,并且可以访问到更多的数据量,不过并不能保证不会被封号。最后将爬取数据保存为csv文件,方便后期使用pandas等做数据处理。
## 非完整代码,毕业设计找丹成学长,q746876041
import csv
import pymysql
import requests
import re
from lxml import html
import time
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
}
# 读取电影url
urls = []
with open('./豆瓣电影TOP250链接.csv', 'r') as f:
reader = csv.reader(f)
urls = [row[0] for row in reader]
for i in range(0, len(urls)):
url = urls[i]
# 请求页面
r = requests.get(url=url, headers=headers, timeout=5)
time.sleep(2)
etree = html.etree
selector = etree.HTML(r.text)
# 获取电影名称
filmname = []
try:
filmname = selector.xpath('//*[@id="content"]/h1/span[1]/text()')[0] # 电影名
if filmname == "":
filmname = None
except Exception as e:
filmname = None
print("filmname :{}".format(filmname))
# 获取电影评分
score = []
try:
score_list = selector.xpath('//*[@id="interest_sectl"]/div[1]/div[2]/strong/text()')
score = score_list[0].replace("\t", "").replace("\n", "")
if score == "":
score = None
except Exception as e:
score = None
print("score :{}".format(score))
# 获取电影上映时间
showtime = []
try:
st = selector.xpath('//*[@id="content"]/h1/span[2]/text()')[0] # 上映日期
showtime = st.replace("(", "").replace(")", "")
if showtime == "":
showtime = None
except Exception as e:
showtime = None
print("time :{}".format(showtime))
# 获取电影片长
mins = []
try:
mins_list = re.findall('片长:.*?>(.*?)', r.text, re.S) # 片长
mins = mins_list[0].replace(' ', '').replace('分钟', '')
if mins == "":
mins = None
except Exception as e:
mins = None
print("mins :{}".format(mins))
# 获取电影类型
genres_list = []
try:
genres_list = re.findall('(.*?)', r.text, re.S)
genres_list = '/'.join(genres_list)
if genres_list == "":
genres_list = None
except Exception as e:
genres_list = None
print("genres_list :{}".format(genres_list))
# 获取电影制片地区
area_list = []
try:
area_list = re.findall('制片国家/地区: (.*?)
', r.text, re.S)
area_list = '/'.join(area_list).replace(' ', '')
if area_list == "":
area_list = None
except Exception as e:
area_list = None
print("area_list :{}".format(area_list))
# 获取电影导演
directors_list = []
try:
d_list = selector.xpath('//div[@id="info"]/span[1]/span[2]/a/text()') # 导演
if len(d_list) > 2:
for i in range(0, 3):
directors_list.append(d_list[i])
else:
for j in range(0, len(d_list)):
directors_list.append(d_list[j])
directors_list = '/'.join(directors_list)
if directors_list == "":
directors_list = None
except Exception as e:
directors_list = None
print("directors_list :{}".format(directors_list))
# 获取电影编剧
scriptwriters_list = []
try:
w_list = selector.xpath('//*[@id="info"]/span[2]/span[2]/a/text()') # 编剧
if len(w_list) > 2:
for i in range(0, 3):
scriptwriters_list.append(w_list[i])
else:
for j in range(0, len(w_list)):
scriptwriters_list.append(w_list[j])
scriptwriters_list = '/'.join(scriptwriters_list)
if scriptwriters_list == "":
scriptwriters_list = None
except Exception as e:
scriptwriters_list = None
print('scriptwriters_list :{}'.format(scriptwriters_list))
# 获取电影主演
actors_list = []
try:
actors = selector.xpath('//*[@id="info"]/span[3]/span[2]')[0] # 演员
a_list = actors.xpath('string(.)').replace(' ', '').split('/') # 标签套标签,用string(.)同时获取所有文本
if len(a_list) > 2:
for i in range(0, 3):
actors_list.append(a_list[i])
else:
for j in range(0, a_list):
actors_list.append(a_list[j])
actors_list = '/'.join(actors_list)
if actors_list == "":
actors_list = None
except Exception as e:
actors_list = None
print('actors_list :{}'.format(actors_list))
# 获取电影评价
comment = []
try:
comment = selector.xpath('//*[@id="interest_sectl"]/div[1]/div[2]/div/div[2]/a/span/text()')[0]
if comment == "":
comment = None
except Exception as e:
comment = None
print("comment :{}".format(comment))
try:
# 打开数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='douban', charset='utf8')
# 使用cursor方法创建一个游标
cursor = conn.cursor()
# # 执行sql语句
query = 'insert into tb_film(url, filmname, score, showtime, genres, areas, mins, directors, scriptwriters, actors, comments) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)'
values = (
url, filmname, score, showtime, genres_list, area_list, mins, directors_list, scriptwriters_list,
actors_list,
comment)
cursor.execute(query, values)
# 提交之前的 *** 作,如果之前已经执行多次的execute,那么就都进行提交
conn.commit()
except Exception as e:
print(e)
# 回滚
conn.rollback()
# 关闭cursor对象
cursor.close()
# 关闭数据库连接
conn.close()
## 非完整代码,毕业设计找丹成学长,q746876041
爬虫输出如下:
4.2 数据分析部分针对某部电影的数据分析
从不同时期影评人数、影评推荐指数、短评内容三个角度入手分析,不同时期的影评人数可以间接反映电影的热度,因为大多数人都是在电影刚上映观影完后写的影评;影评推荐指数可以直接看出观众对电影的喜好程度,对最热门的评论的汇总更能体现这部电影在大众中的影响力,而不是单靠官方给出的豆瓣评分;短评词云可以体现电影的许多要素,比如演员、题材、主要情节剧情、观众评价,可以让影迷马上把握该电影脉搏,从而决定这部电影是否值得一看。
随机多部电影的综合数据分析
如果说针对某部电影的分析是让影迷决定是否看该部电影,那么随机多部电影的综合分析结果就是指引影迷去观看哪部电影。使用随机序号生成器在热门电影列表中任意选择电影,然后可视化出电影评分排行榜、电影Top20高分排行榜,电影上映时间线和电影类型分布,多方位直观俯瞰热门电影行情。对于大众来说可以得知哪些电影近期更受欢迎,哪些电影评分高,电影在哪个时间段上映,从而发现自己喜欢的电影和属于自己的电影偏好。对于电影制作方,可以针对电影类型分布,保持哪些电影类型的产出,加大哪类电影的制作投入以顺应大众口味,甚至可以决策在什么时候上映哪些类型的电影能获得最大收益。
## 非完整代码,毕业设计找丹成学长,q746876041
import pymysql
from pyecharts import options as opts
from pyecharts.charts import Timeline, Bar, Grid
# 上映年份
showtime = []
# 查询中外电影上映年份
def select_showtime():
try:
# 打开数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='douban', charset='utf8')
# 使用cursor方法创建一个游标
cursor = conn.cursor()
# 查询数据表数据
# 查询上映年份
sql = "select distinct showtime from tb_film where showtime is not null order by showtime "
cursor.execute(sql)
rows = cursor.fetchall()
showtime.clear()
for row in rows:
showtime.append(row[0])
print(showtime)
except Exception as e:
print(e)
# 回滚
conn.rollback()
finally:
# 关闭cursor对象
cursor.close()
# 关闭数据库连接
conn.close()
return showtime
# 查询电影名称、评分
def select_film(i):
# 电影名称集合
filmname = []
# 评分集合
score = []
try:
# 打开数据库连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123456', db='douban', charset='utf8')
# cursorclass = pymysql.cursors.DictCursor
# 使用cursor方法创建一个游标
cursor = conn.cursor()
# 查询数据表数据
# 查找评分前十的电影名称、评分
cursor.execute(
"select filmname,score from tb_film where score is not null and showtime > 0 and showtime <= %s order by score desc limit 10",
i)
# 电影名称、评分集合
film_list = cursor.fetchall()
for row in film_list:
# 电影名称集合
filmname.append(row[0])
# 评分集合
score.append(row[1])
filmname.reverse()
score.reverse()
# 最大值
max_score = max(score)
# 最小值
min_score = min(score)
except Exception as e:
print(e)
# 回滚
conn.rollback()
finally:
# 关闭cursor对象
cursor.close()
# 关闭数据库连接
conn.close()
return filmname, score, max_score, min_score
def select_data(year):
film_list = select_film(year)
colors = [
"#546570", "#c4ccd3", "#bda29a", "#ca8622", "#d48265",
"#6e7074", "#749f83", "#61a0a8", "#2f4554", "#c23531",
"#6e7074", "#749f83", "#61a0a8", "#2f4554", "#c23531"
]
y = []
for n in range(len(film_list[1])):
y.append(
opts.BarItem(
name=film_list[0][n],
value=film_list[1][n],
itemstyle_opts=opts.ItemStyleOpts(color=colors[n]),
)
)
return y
def show_score_top():
# 查找上映年份集合
showtime=select_showtime()
# 生成时间轴的图
timeline = Timeline(init_opts=opts.InitOpts(page_title="豆瓣电影TOP250-评分TOP10的电影", ))
for year in showtime:
film_tuple=select_film(year)
date_list=select_data(year)
timeline.add_schema(is_auto_play=True, play_interval=1000)
# 柱状图初始化
bar = Bar()
# 横坐标
bar.add_xaxis(film_tuple[0])
# 纵坐标
bar.add_yaxis(
"",
date_list,
# 数据靠右显示
label_opts=opts.LabelOpts(is_show=True, position='right')
)
# 横纵坐标翻转
bar.reversal_axis()
# 全局配置
bar.set_global_opts(
# 标题
title_opts=opts.TitleOpts(title="豆瓣电影TOP250-第{}年评分TOP10的电影".format(year), pos_left='center'),
# 横坐标隐藏
xaxis_opts=opts.AxisOpts(is_show=False, max_=select_film(year)[2], min_=(float(select_film(year)[3]) - 0.1),
split_number=10),
# 纵坐标
yaxis_opts=opts.AxisOpts(
max_=9,
# 字体大小
axislabel_opts=opts.LabelOpts(font_size=10),
# 隐藏坐标轴
axisline_opts=opts.AxisLineOpts(is_show=False),
# 隐藏刻度
axistick_opts=opts.AxisTickOpts(is_show=False)
)
)
# 组合组件
grid = (
Grid()
.add(bar, grid_opts=opts.GridOpts(pos_top='8%', pos_bottom='12%', pos_left='25%'))
)
timeline.add(grid, "{}年".format(year))
timeline.add_schema(is_auto_play=True, play_interval=1000, is_loop_play=False, width='820px', pos_left='60px')
# 生成HTML
html = "pages/iframes/score_top.html"
timeline.render("./templates/" + html)
return html
## 非完整代码,毕业设计找丹成学长,q746876041
5 最后-毕设帮助
毕设帮助,开题指导,技术解答
🇶746876041
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)