Pythonweb可视化页面(豆瓣电影爬取)

目标:

豆瓣电影爬虫系统:爬取豆瓣电影网站的数据,实现在网站上显示正在热映的10部电影(词云图)、评分最高的10部电影(散点图)以及主演电影数量最多的10位演员(条形图)的相关图形。

思维导图:

下面进行讲解:

电影爬虫:

1. 首先我们需要先导入模块和创建csv保存路径。

import re
import requests
import csv
from lxml import etree
import time
import os

# 定义文件路径
file_path = 'movies.csv'


with open(file_path, 'w', encoding='utf-8-sig') as f:
    #指定了文件的编码为'utf-8-sig'以及不自动添加换行符(newline='')
    writer = csv.writer(f, dialect='excel')
    #'excel'是一个常用的格式,它使用逗号作为字段分隔符,双引号作为字段的包围字符,并处理包含逗号、换行符或双引号的字段。也可以注释,默认的足以使用。
    writer.writerow(['电影名称', '电影评分', '电影排名', '导演', '主演', '电影海报地址', '上映日期', '电影国家', '电影类型'])
    #使用writerow方法向CSV文件中写入一行数据,这里作为头部信息。
    这里使用writerow方法向CSV文件中写入一行数据,后面的数据也保存到对应的列。

2.下面是请求豆瓣top250de1数据,


# 定义get请求函数
def get_page(url):
    #定义请求头headers
    try:
        headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
        }
        #发送get请求
        res=requests. Get(url=url,headers=headers)
        #判断请求是否成功
        if res.status_code==200:
            response=res.content.decode("utf-8")
            return response
        else:
            return False
    except:
        return False
headers是请求头,可以通过谷歌来看,个人感觉比较清晰明了。

下面是对要爬取的数据进行正则化处理的具体代码:

#定义数据解析函数
def parse_data(html,url):
    #数据解析一些内容有的需要xpath 有的需要正则
    html = etree.HTML(html)
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'
    }
    res = requests.get(url=url, headers=headers)
    response = res.content.decode("utf-8")

    #电影名称
    movie_title=html.xpath("//div[@class='hd']//a//span[1]//text()")
    #电影评分
    movie_score=html.xpath('//div[@class="star"]//span[2]//text()')
    #电影排名
    movie_degree=html.xpath('//div[@class="item"]//div//em//text()')
    #电影海报地址
    movie_poster=html.xpath('//div[@class="pic"]//a//img/@src')
    #导演,使用正则
    movie_director = re.findall(r"导演:(.*?);", response)
    a = "".join(movie_director).split("&nbsp")#因为使用的正则抓取下来的字符串含有&nbsp,使用split()函数进行切分
    movie_director = a[:25]
    if movie_director=="":
        movie_director=""
    else:
        movie_director=movie_director
    #主演,使用正则
    movie_main_act = re.findall("主演: (.*)<br>", response)
    movie_main_act = "".join(movie_main_act).split("...")
    if movie_main_act=="":
        movie_main_act=""
    else:
        movie_main_act=movie_main_act
    #上映日期
    movie_datatime= re.findall(r"(\d*)&nbsp;", response)
    b = "".join(movie_datatime)#转化为字符串
    movie_datatime = [b[i:i + 4] for i in range(0, len(b), 4)]#转换的字符串是一对数字如199419931994....,所以进行切分 4个一切就是年份
    if movie_datatime=="":
        movie_datatime=""
    else:
        movie_datatime=movie_datatime
    #电影国家
    movie_country= re.findall("&nbsp;/&nbsp;(.*?)&nbsp;", response)
    movie_type= html.xpath("//div[@class='bd']/p/text()[2]")
    n = ''.join([' '.join([i.strip() for i in price.strip().split('\n')]) for price in movie_type][::2]).split("\xa0/\xa0")#转换为字符串进行切分

    l = n[2::2]#因为上面的n列表我们包含的电影类型,所以n[2::2]操作把包含类型都取出来
    o = ''.join(l)#转换为字符串
    h = re.sub("\d{4}", ";", o)#使用正则将数字全都用;符号代替
    movie_type = h.lstrip("\n")#这个之前打印的最左边有一个\n符号  所以使用lstrip()函数去掉
    movie_type = movie_type.split(";")#然后用字符串split()函数以;符号进行切分
    if movie_type=="":
        movie_type=""
    else:
        movie_type=movie_type
    for a,b,c,d,e,f,g,h,i in list(zip(movie_title,movie_score,movie_degree,movie_director,
                                 movie_main_act, movie_poster,movie_datatime,movie_country,movie_type)):
        print(a,b,c,d,e,f,g,h,i)
     # 写入
        with open('movies.csv', 'a', encoding='utf-8-sig', newline='') as f:
            writer = csv.writer(f, dialect='excel')
            writer.writerow([a, b, c, d, e, f, g, h, i])


def main(num):
    #定义url
    url=f'https://movie.douban.com/top250?start={num}'
    # 调用发送get请求函数
    html=get_page(url)
    # 如果发送请求成功,执行解析数据函数
    if html:
        parse_data(html,url)

运行结果:

python可视化大屏展示:

我是先将子图开发出来,然后用pyecharts的Page组件,把这些子图表拖拽组合起来,形成html大屏。 

pyecharts是一个用于生成各种图表的Python库,支持丰富的图表类型,包括饼图、柱状图、折线图等。

导入所需的:

from plotly.graph_objs import Bar
from pyecharts.charts import WordCloud, EffectScatter, Page, Pie
import pandas as pd
from pyecharts.charts import Bar
from pyecharts import options as opts
from pyecharts.globals import ThemeType

 标题:


csv_file_path = 'your csv path'  # 替换为你的CSV文件路径,我们刚刚生成的。
# 自定义HTML标题
folder = ''
def tab1(name, color):  # 标题
    c = (Pie(init_opts=opts.InitOpts(theme=ThemeType.CHALK)).
        set_global_opts(
        title_opts=opts.TitleOpts(title=name, pos_left='center', pos_top='center',
                                  title_textstyle_opts=opts.TextStyleOpts(color=color, font_size=36))))
    return c

注意:在这个tab1函数中,c是一个Pie对象(来自于pyecharts库),该对象代表了一个饼图(Pie chart)的配置和数据结构。通过链式调用set_global_opts方法来设置全局配置项。

因为pyecharts组件没有专门用作标题的函数,所以直接运用Pie来实现标题的效果,没有添加数据。

运行结果:

条形图:


def create_actor_bar_chart(csv_file_path):  #条形图
    # 读取CSV文件
    movie_data = pd.read_csv(csv_file_path, encoding='utf-8')

    # 统计演员的作品数量
    actor_counts = movie_data.iloc[:, 4].value_counts()  # 假设第五列是演员名称
    top_actors = actor_counts.head(10)  # 获取作品数量前十的演员

    # 准备数据
    actors = top_actors.index.tolist()
    counts = top_actors.values.tolist()

    # 创建 Bar 对象
    bar = (
        Bar(
            init_opts=opts.InitOpts(theme=ThemeType.CHALK)
        )
            .add_xaxis(actors)
            .add_yaxis("作品数量", counts)
            .set_global_opts(
            title_opts=opts.TitleOpts(title="主演电影数量最多的10位演员", pos_left='center'),
            xaxis_opts=opts.AxisOpts(name="演员", axislabel_opts=opts.LabelOpts(rotate=45)),
            yaxis_opts=opts.AxisOpts(name="作品数量"),
            legend_opts=opts.LegendOpts(is_show=False),
        )
            .set_series_opts(
            label_opts=opts.LabelOpts(is_show=True, position="inside", color="#fff"),
            markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="最大值")]),
        )
        )

    return bar

因为求主演电影数量最多的10位演员(以条形图)的形式展示出来,所以需要actors和counts的对应数据,然后才能创建Bar对象,因为演员名字有较长还定义了markpoint_opts(用于高亮显示数据中的最大值)。

运行结果:

 散点图:

#生成散点图
def create_movie_scatter_chart(csv_file_path):
    # 读取CSV文件
    try:
        movie_data = pd.read_csv(csv_file_path, encoding='utf-8')
    except FileNotFoundError:
        print(f"文件未找到: {csv_file_path}")
        return None

    # 获取前十个电影名称和评分
    top_movies = movie_data.head(10)[['电影名称', '电影评分']].values.tolist()

    # 检查top_movies是否为空
    if not top_movies:
        print("没有有效数据,无法生成散点图")
        return None

    # 创建散点图
    sc = EffectScatter(init_opts=opts.InitOpts(width="600px", height="400px",theme=ThemeType.CHALK))

    # 提取电影名称和评分,准备添加到图表中
    x_data, y_data = zip(*top_movies)

    # 添加数据到图表
    sc.add_xaxis(x_data)  # 电影名称
    sc.add_yaxis("电影评分", y_data, symbol_size=10, label_opts=opts.LabelOpts(is_show=False))  # 电影评分

    # 设置X轴和Y轴
    xaxis_opts = opts.AxisOpts(
        type_="category",
        name="电影名称",
        axislabel_opts=opts.LabelOpts(rotate=45)  # 调整标签旋转角度以便更好地显示
    )

    yaxis_opts = opts.AxisOpts(
        name="电影评分",
        type_="value"
    )

    # 设置全局选项
    sc.set_global_opts(
        title_opts=opts.TitleOpts(title='评分最高的10部电影'),
        xaxis_opts=xaxis_opts,
        yaxis_opts=yaxis_opts,
        tooltip_opts=opts.TooltipOpts(is_show=False),
    )

    return sc

同样需要先准备数据,然后创建对象。

运行结果:

词云图:

# 定义一个函数来生成词云图
def filmname_wordcloud(csv_file_path):
    # 读取CSV文件
    df = pd.read_csv(csv_file_path)
    print(df['电影名称'])
    data = df['电影名称'].value_counts(30).head(600)  # 取最常见的词

    #设置图表初始化选项的一种方式。
    #init_opts参数通常作为图表类(如Pie、Bar、Line等)的构造函数的一个参数来传递。
    # 创建词云图实例
    wc = WordCloud(init_opts=opts.InitOpts(width="450px", height="350px",theme=ThemeType.CHALK))

    # 添加词云图数据
    # 假设每个词的出现都是一次,创建数据对

    wc.add(series_name="电影名称",
           data_pair=list(zip(data.index.tolist(), data.tolist())),  # 将Series转换为数据对列表
           word_size_range=[15, 60],  # 根据需要调整单词字体大小范围
           width='400px',  # 宽度
           height='300px',  # 高度
           word_gap=1  # 单词间隔
           )

    # 设置全局配置项
    wc.set_global_opts(
        title_opts=opts.TitleOpts(pos_left='all',
                                  title="正在热映的10部电影",
                                  title_textstyle_opts=opts.TextStyleOpts(font_size=18)
                                  ),

        tooltip_opts=opts.TooltipOpts(is_show=False)  # 显示提示框
    )

    return wc

运行结果:

Page拖拽组合:

上面我们已经生成了词云图,散点图,条形图以及标题(饼图),下面我们通过

layout=Page.DraggablePageLayout组合起来,并且导入实参。

page = Page(page_title="基于Python的电影数据分析大屏",
            layout=Page.DraggablePageLayout)
page.add(
         tab1("数据可视化大屏", "black"),
         create_movie_scatter_chart(csv_file_path),
         create_actor_bar_chart(csv_file_path),
         filmname_wordcloud(csv_file_path))
page. Render("test.html")

代码执行后,会生成一个test,html的可拖拽页面,可以自由组合自己喜欢的排列方式。

注意,页面的左上角会有一个小小的图标。

排列好后,点击它,会生成一个json,里面是配置的位置信息。

执行新建的py文件,会生成最终的html页面(不可拖拽)。

最终运行结果:

我这里为了符合题意采用的数据较少,可以修改对应的参数来增加美观。

 这里我引用了的一些想法和思路,如有侵权请联系我,谢谢。【Python可视化大屏】全流程讲解pyecharts拖拽可视化大屏的背后原理_python 可视化拖拉拽-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值