爬取电影数据结合Flask实现数据可视化

news/2025/1/10 14:14:01/

网站:Scrape | Movie

本案例(爬虫)所需要的模块
requests  (网络请求模块)pandas (数据保存模块)
parsel   (数据解析模块)lxml (数据解析模块)

pyecharts (可视化库)flask(框架)

以上的模块均需要通过 指令 pip install 模块名 安装

 Explain:
        分析此页面的数据为静态的还是动态加载的  右击打开查看页面源代码 可知此网站的数据为静态的 
        我们所需要采集的数据都在里面


 



爬取步骤: 
一. 发送请求 模拟浏览器向服务器发送请求

        F12 打开开发者工具 or 右击打开检查
        接着分析html代码的结构 找出数据的所在位置
        Class属性为(
el-card item m-t is-hover-shadow) div 包含我们的数据
        通过类名拿到之后遍历取值

        

python"># 导包 导入所需要的模块 库
import requests
import parsel
from lxml import etreeimport pandas as pdurl = f'https://ssr1.scrape.center/page/{page}'
# 因为此网站无反爬 不需要加额外参数的请求头
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0','referer': 'https://ssr1.scrape.center/page/2'
}
resp = requests.get(url, headers=headers)
# 实例一个selector对象
selector = parsel.Selector(resp.text)
# css 语法 获取所有的div
lis = selector.css('.el-card.item.m-t.is-hover-shadow')

 进一步分析  各个数据的位置

电影名称    .m-b-sm::text  提取里面的文本
电影类型    .categories span::text  拿到所有的span标签中的文本
电影区域|上映时间|电影时长  .m-v-sm.info span::text  同上

详情页链接  .name::attr(href)  拿到详情页里面的剧情介绍

二. 解析数据 

 电影类型:

电影区域|上映时间|电影时长:

评分:

 

多页的数据采集


page 参数的不同 可以嵌套for循环实现
 


三. 提取数据 提取所需要的数据

python">import requests
import parsel
from lxml import etreeimport pandas as pd# 多页爬取
for page in range(1,11):url = f'https://ssr1.scrape.center/page/{page}'headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0',# 多页爬取最好加个防盗链'referer': 'https://ssr1.scrape.center/page/2'}resp = requests.get(url, headers=headers)selector = parsel.Selector(resp.text)# 解析成htmlhtml = etree.HTML(resp.text)lis = selector.css('.el-card.item.m-t.is-hover-shadow')for li in lis:title = li.css('.m-b-sm::text').get()# 转换成字符串 处理成想要的数据score = ''.join(html.xpath("//*[@class ='score m-t-md m-b-n-sm']/text()")[0]).strip()type = ' '.join(li.css('.categories span::text').getall())# 对得到的列表数据取值area = li.css('.m-v-sm.info span::text').getall()[0]time = li.css('.m-v-sm.info span::text').getall()[-2]upload_time = li.css('.m-v-sm.info span::text').getall()[-1]# 电影封面数据img_url = li.css('.cover::attr(src)').get()# 电影内页链接href = li.css('.name::attr(href)').getall()# for 循环遍历 拼接URL 地址获取剧情简介for i in href:inner_url = 'https://ssr1.scrape.center' + iresponse = requests.get(url=inner_url, headers=headers)inner_select = parsel.Selector(response.text)# 获取数据 转换成字符串introduce = ''.join(inner_select.css('.drama p::text').get()).strip()# 用字典封装起来dit = {"title": title,"score": score,"type": type,"area": area,"time": time,"upload_time": upload_time,"introduce": introduce,"img_url": img_url,}

四.保存数据  保存数据到本地

python"># 定义一个空列表
all = []
# 将字典数据添加到列表中
all.append(dit)
# 通过pandas 保存数据 不保存索引
pd.DataFrame(all).to_excel('movie_info.xlsx', index=False)

完整代码如下:
           仅供学习参考

python">import requests
import parsel
from lxml import etreeimport pandas as pdall = []
for page in range(1,11):url = f'https://ssr1.scrape.center/page/{page}'headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0','referer': 'https://ssr1.scrape.center/page/2'}resp = requests.get(url, headers=headers)selector = parsel.Selector(resp.text)html = etree.HTML(resp.text)lis = selector.css('.el-card.item.m-t.is-hover-shadow')for li in lis:title = li.css('.m-b-sm::text').get()score = ''.join(html.xpath("//*[@class ='score m-t-md m-b-n-sm']/text()")[0]).strip()type = ' '.join(li.css('.categories span::text').getall())area = li.css('.m-v-sm.info span::text').getall()[0]time = li.css('.m-v-sm.info span::text').getall()[-2]upload_time = li.css('.m-v-sm.info span::text').getall()[-1]img_url = li.css('.cover::attr(src)').get()href = li.css('.name::attr(href)').getall()for i in href:inner_url = 'https://ssr1.scrape.center' + iresponse = requests.get(url=inner_url, headers=headers)inner_select = parsel.Selector(response.text)introduce = ''.join(inner_select.css('.drama p::text').get()).strip()dit = {"title": title,"score": score,"type": type,"area": area,"time": time,"upload_time": upload_time,"introduce": introduce,"img_url": img_url,}all.append(dit)pd.DataFrame(all).to_excel('movie_info.xlsx', index=False)

 运行 数据采集成功

处理数据 将想要的字段数据可视化 生成图表

python">#导包
import pandas as pd
from pyecharts.charts import Line
# 配置项
from pyecharts import options as opt# 读取文件
df = pd.read_excel('movie_info.xlsx')
title = df['title'].tolist()
score = df['score'].tolist()
bar =(Line()# 添加x y轴数据.add_xaxis(title)# 显示最大最小值的数据.add_yaxis('评分',score,markpoint_opts=opt.MarkPointOpts(data=[opt.MarkPointItem(type_='max'),opt.MarkPointItem(type_='min'),]))# 设置标题.set_global_opts(title_opts=opt.TitleOpts(title='电影信息评分'),)# 隐藏其它的数值.set_series_opts(label_opts=opt.LabelOpts(is_show=False))
).render('score.html')
# 生产html文件

接着渲染到Flask上

  render_template它是一个用于渲染模板文件的函数。在 Flask 中,通常会将 HTML 页面等内容写在模板文件里(比如使用 Jinja2 模板引擎的模板文件),这个函数能够将模板文件与 Python 代码中的数据结合起来,生成最终要返回给客户端的 HTML 页面等内容。


python">from flask import Flask,render_template,request#这里实例化了 Flask 类,创建了一个 Flask 应用对象,并将当前模块的名称(通过 Python 内置的 __name__ 变量获取)传递给 Flask 类的构造函数。这个应用对象是后续定义路由、启动服务器等操作的基础
app = Flask(__name__)
# 设置路由
# 是一个装饰器,用于将一个 Python 函数(在这里是 view 函数)与一个特定的 URL 路径进行绑定,也就是定义了一个路由。在这个例子中,/ 表示应用的根路径,意味着当用户通过浏览器访问这个 Flask 应用的根 URL(比如 http://localhost:5000/,默认运行在 5000 端口)时,view 函数就会被调用
@app.route('/')
def view():return render_template('view.html')if __name__ == '__main__':# 服务器的启动方式 通过刷新就可以实时查看app.run(debug=True)

点击就可以打开服务器看到我们渲染的图表了 



本次的案例分享就到此结束感谢您的观看
您的点赞和关注是我更新的动力 后续我也会持续学习


http://www.ppmy.cn/news/1561993.html

相关文章

flask-admin 非自定义modelview下扩展默认视图(base.html)

背景 在默认视图下实现某些统一的业务需求,如想改变默认视图的某些样式等。本文想阐述的是在默认视图下添加“面包屑”效果 材料: 略 制作: 目标: 1、在不重构的情况下实现如下效果 2、上源码 {% if admin_view.category %}…

C#中 string.Equals 和 == 区别

在 C# 中,string.Equals方法和运算符都可用于比较字符串,但它们在某些方面存在区别,主要如下: **string.Equals方法:**是一个实例方法,用于比较两个字符串对象的内容是否相等,比较时会根据字符…

QT笔记- QTableWidget移动行

QTableWidget * tw ui->tableWidget;// 保存要移动的行的数据QList<QTableWidgetItem *> items;for(int i 0; i < 2; i){QTableWidgetItem * C0Item;QTableWidgetItem * C1Item;QTableWidgetItem * C2Item;int removeRow -1;for(int row 0; row < tw->ro…

Android studio gradle与gradle插件

最终换gradle版本&#xff0c;糊成一坨。 记录一下 Android studio里有两个容易搞混&#xff0c;记载一下。 build.gradle文件中的为插件版本&#xff1a; classpath "com.android.tools.build:gradle:3.5.0" gradle.properties里的才是gradle版本。 distributio…

飞书企业消息实践

一、飞书自带的消息机器人限制 频控策略 - 服务端 API - 飞书开放平台 自定义机器人的频率控制和普通应用不同&#xff0c;为单租户单机器人 100 次/分钟&#xff0c;5 次/秒。建议发送消息尽量避开诸如 10:00、17:30 等整点及半点时间&#xff0c;否则可能出现因系统压力导致…

什么是数据湖?大数据架构的未来趋势

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

JS控制对应数据隐藏

首先需要获得到所有的input框&#xff0c;并声明一个空对象来存放&#xff0c;遍历所有的复选框&#xff0c;将他们中选中的放入对象&#xff0c;并设置键值为true&#xff0c;然后执行checkFalseValues(result)函数 function hideItem() {let checkboxes $(.setting_box inp…

(二)最长公共子序列、最长上升子序列、最大子段和、三角形最小路径和、矩阵连乘、0-1背包

最近刚考完算法设计分析课的考试&#xff0c;复习总结一下期末考试的几道算法题吧 目录 LCR 095. 最长公共子序列 300. 最长递增子序列 53. 最大子数组和 LCR 100. 三角形最小路径和 矩阵连乘问题 0-1背包 LCR 095. 最长公共子序列 给定两个字符串 text1 和 text2&#xff…