Python+Flask豆瓣电影爬虫可视化系统实战
简介这是一套基于Python和Flask框架的豆瓣电影爬虫采集与分析可视化系统毕业设计源码适合计算机相关专业用于毕业设计、期末大作业或课程设计。项目实现了从豆瓣电影页面爬取数据、清洗存储到后端分析并通过Web界面进行可视化展示的完整流程评审得分98分本地编译运行通过。资源包共110个文件涵盖Python后端逻辑、HTML/CSS/JavaScript前端页面、数据库文件、配置文件及说明文档等压缩包仅6.25MB结构清爽便于快速部署与二次开发。前端基于Bootstrap构建响应式界面后端包含爬虫脚本与数据处理模块并提供数据可视化图表。目前已有241人学习下载。交付内容包含可运行源码、前端静态资源、数据文件以及必要的使用说明可帮助学习者直观理解爬虫与Flask Web开发的结合方式适合希望完成高质量课设或毕业设计的学生参考。1. 用PythonFlask把豆瓣电影爬虫做成能答辩的可视化系统豆瓣电影Top250是很多人的第一个爬虫目标但真正把它做成毕业设计难点不在爬而在把采集、清洗、存储、接口、可视化串成一条完整的链路。标题里的“Pythonflask”划定了技术选型爬虫负责拿数据Flask在中间做Web服务层可视化把数据变成能展示的图表。这种结构背后是毕业设计最常见的三层架构——数据采集层、服务层、展示层。适合的人群很明确需要交代码和文档的本科生、想把这套流程迁移到其他站点的爬虫新手还有想搞清楚Flask和ECharts如何配合的Web开发者。这篇文章按我自己实现这套系统的顺序来写从反爬参数到SQLite入库再到Flask接口和图表渲染最后落到排错和答辩准备。2. 先说采集豆瓣电影Top250的爬虫方案与反爬参数设置2.1 选requests而不是Scrapy毕业设计场景的性价比判断很多教程一上来就推Scrapy但对“基于Pythonflask豆瓣电影爬虫采集与分析可视化系统”这样的标题requests反而是更合理的选择。原因有两层第一Top250总共只有10页数据采集量在几百条量级Scrapy的异步并发优势完全发挥不出来第二这个系统的核心展示层是Flaskrequests写出来的代码更直观评阅老师读代码时不需要理解爬虫框架的中间件机制。如果你后续想把采集规模扩大再把requests代码改造成Scrapy的Spider也不难接口逻辑是通用的。另外还要决定用什么解析库。常见做法是BeautifulSoup加lxml解析器或者直接用lxml的xpath。对于豆瓣这种HTML结构相对稳定的页面xpath的表达式写起来更紧凑而且lxml的解析速度明显快于纯Python的html.parser。我一般用lxml后面所有解析示例都按这个来。2.2 豆瓣Top250的URL规律start参数与翻页控制豆瓣Top250的列表页遵循一个固定规律每页显示25条通过URL里的start参数控制偏移量。第一页是start0第二页是start25第三页是start50以此类推。拿到这个规律后翻页就变成了一个循环import requests from lxml import html base_url https://movie.douban.com/top250 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36, Referer: https://movie.douban.com/top250 } for page in range(10): start page * 25 resp requests.get(base_url, params{start: start, filter: }, headersheaders, timeout10) print(f第{page 1}页状态码: {resp.status_code})这里params参数是关键。requests会把{start: start, filter: }自动编码成查询字符串拼到URL后面不需要手动做字符串拼接。timeout10是必写的否则遇到网络抖动时请求会一直挂住程序卡死在循环里。每页抓取之间建议加一个time.sleep(2)既是对目标站点的基本礼貌也是降低触发反爬概率的最简单手段。2.3 请求头伪装与限速User-Agent、Referer、Cookie的取舍豆瓣的常规反爬策略并不复杂主要看请求头是否像真实浏览器。最需要伪装的是User-Agent其次是Referer。UA的格式要完整不能只写python-requests这种默认值至少带操作系统信息和浏览器版本。Referer填首页地址避免请求被识别为孤立请求。2.3.1 请求头参数对照表参数推荐值作用User-Agent带Windows/macOS标识的浏览器UA绕过最基础的UA检测Refererhttps://movie.douban.com/top250模拟从站内页面跳转过来的请求Cookie浏览器里复制的一段完整Cookie解决部分时段验证码提前触发的问题timeout10秒避免连接挂起拖死采集进程Cookie不需要专门处理直接在浏览器里登录豆瓣后从开发者工具的请求头里复制粘贴到代码中即可。比较稳妥的做法是把Cookie、UA这些放到一个配置文件或环境变量里代码里用os.getenv()读取而不是写死在脚本里这样以后换机器跑不用改代码。2.4 清洗与SQLite入库编码是第一个坑解析页面时最容易翻车的地方是编码。豆瓣页面是UTF-8编码但如果直接用resp.textrequests会根据响应头猜测编码偶尔会猜错导致中文乱码。保险的做法是直接用resp.content解码parser html.fromstring(resp.content.decode(utf-8)) items parser.xpath(//div[classitem]) movie_list [] for item in items: title item.xpath(.//span[classtitle]/text())[0] rating item.xpath(.//span[classrating_num]/text())[0] people item.xpath(.//div[classstar]/span[4]/text())[0] quote item.xpath(.//p[classquote]/span/text()) movie_list.append({ title: title, rating: float(rating), people: int(people.replace(人评价, )), quote: quote[0] if quote else })解码逻辑先取原始字节流resp.content再按UTF-8显式解码彻底绕开resp.text的编码猜测逻辑。清洗的重点有两个一个是人评价这个字符串要去掉才能转成整数另一个是quote字段不是每条都有要用列表判断兜底否则取下标会抛IndexError。数据入库用Python内置的sqlite3模块就够了不需要额外引入SQLAlchemy毕业设计项目用标准库能少装一个依赖运行环境出问题的概率也小。3. Flask后端把爬虫结果变成可查询的Web接口3.1 项目结构与爬虫模块的边界划分爬虫代码和Flask代码不能混在一个文件里。我见过很多学生把requests.get直接写在路由函数里这样每次打开页面都重新抓一遍速度慢且容易被封。合理的结构是把爬虫写成一个独立的模块只在需要更新数据时才执行Flask只负责读数据库douban_project/ ├── app.py # Flask入口 ├── spider.py # 爬虫采集模块 ├── db.sqlite3 # SQLite数据库文件 └── templates/ └── index.html # 可视化页面模板采集入库和Web服务在这个结构里被拆开了spider.py跑一次是刷新数据app.py启动后永远只做查询和渲染。这样设计还有一个好处采集频率可以被明确控制不会因为用户多次刷新页面导致请求风暴。如果你想做定时刷新在spider.py里加一个while True加time.sleep(86400)的循环即可但毕业设计通常不需要。3.2 用Flask暴露电影查询接口Flask部分最核心的接口是“按条件筛选电影”。常见做法是不用render_template直出HTML而是先写一个JSON接口前端页面通过fetch调用。这样分层清晰也方便你在浏览器里直接验证接口返回的数据内容from flask import Flask, jsonify, request import sqlite3 app Flask(__name__) def query_movies(rating_min0, rating_max10, limit20): conn sqlite3.connect(db.sqlite3) conn.row_factory sqlite3.Row sql SELECT title, rating, people, quote FROM movies WHERE rating ? AND rating ? ORDER BY rating DESC LIMIT ? rows conn.execute(sql, (rating_min, rating_max, limit)).fetchall() conn.close() return [dict(row) for row in rows] app.route(/api/movies) def movies_api(): rating_min request.args.get(rating_min, default0, typefloat) rating_max request.args.get(rating_max, default10, typefloat) limit request.args.get(limit, default20, typeint) return jsonify(query_movies(rating_min, rating_max, limit)) if __name__ __main__: app.run(debugTrue)逻辑说明request.args.get从查询字符串中读取参数default指定默认值type指定类型转换。这里用了typefloat和typeint如果用户传了非法值Flask会把参数置为默认值而不是报500错误。sqlite3.Row让查询结果可以按列名取值dict(row)转成普通字典后才能被jsonify正确序列化。3.3 必调参数JSON中文编码、请求方式与debug模式Flask有几个设置项在这个项目里必须处理否则会踩坑。第一个是JSON中文编码。Flask 2.3版本之后默认app.json.ensure_ascii为False中文会正常显示如果你用的是旧版本需要在创建app后设置app.config[JSON_AS_ASCII] False否则接口返回的是\uXXXX格式的Unicode转义序列前端图表解析倒没问题但浏览器直接看接口很难受。第二个是请求方式。查询接口只允许GET足够不需要methods[GET, POST]限定GET反而能让接口语义更清晰。第三个是debugTrue。本地开发阶段必须开改代码自动重载报错时能在页面看到完整的堆栈。但注意app.run(debugTrue)只能用于本机调试交文档或部署演示时不要带这个参数改成app.run(host0.0.0.0, port5000)这样能在同局域网的其他设备上访问演示。3.4 按年份和类型做二次聚合查询Top250数据里评分和评价人数是数值型字段可以直接用于区间过滤但年份和类型是以字符串形式存在的比如“1994”和“剧情 / 爱情”。如果要做“某一年评分最高的电影”或者“某类型电影的平均评分”最方便的办法是入库时就把这些字段拆好而不是每次查询时处理字符串。在SQLite里加两个字段year INTEGER和genre TEXT入库时正则匹配出年份类型按/分割后存第一项。import re def parse_movie(raw): year_match re.search(r(\d{4}), raw[year_text]) genre raw[genre_text].split(/)[0].strip() return { title: raw[title], rating: raw[rating], year: int(year_match.group(1)) if year_match else 0, genre: genre }拆字段的好处到后面可视化阶段会体现出来类型分布统计完全可以用一条GROUP BY genre的SQL完成不需要把全表数据拉到Python里再数数。如果你用的豆瓣数据源字段名不完全一样思路是一样的——入库之前把需要聚合分析的维度全部拆成独立列宁可多存一列也不要让SQL写成LIKE %剧情%这种性能很差的查询。4. 可视化ECharts图表与Flask模板的渲染实战4.1 直出HTML还是前端拉接口两种方案的取舍可视化部分有两种常见做法。第一种是Flask用render_template把数据直接渲染进模板的script标签里页面加载时图表立即显示第二种是模板里放空的div页面加载后用JavaScript通过fetch从/api/movies拿数据再喂给ECharts。我推荐第二种理由很实际接口层已经写好了前端拉数据能让接口和数据展示解耦调试接口不用刷新页面图表渲染失败时也能区分是数据问题还是前端问题。模板里用cdn方式引入ECharts。不需要下载js文件到本地直接引https://cdn.jsdelivr.net/npm/echarts5/dist/echarts.min.js但要注意演示机器必须联网如果答辩现场网络不稳提前下载echarts.min.js放到static目录更保险。4.2 评分分布与类型Top10的聚合SQL可视化图表对应的数据用SQL聚合比用Python循环高效得多也更能体现你对数据分析的掌握程度。评分分布用分段统计在SQL里写CASE WHEN表达式SELECT CASE WHEN rating 9 THEN 9分以上 WHEN rating 8 THEN 8到9分 WHEN rating 7 THEN 7到8分 ELSE 7分以下 END AS rating_level, COUNT(*) AS count FROM movies GROUP BY rating_level;逻辑说明这条SQL把评分分成四段每段统计电影数量返回结果直接就是饼图或柱状图需要的数据格式。GROUP BY的对象是CASE表达式本身SQLite允许按别名分组但为了兼容性这里重复写了完整表达式。类型分布类似SELECT genre, COUNT(*) FROM movies GROUP BY genre ORDER BY count DESC LIMIT 10即可注意genre字段已经拆过不需要处理字符串拼接。4.3 ECharts图表与Flask路由的配合Flask端再加两个路由一个返回评分分布一个返回类型Top10前端一次性拉两个接口app.route(/api/rating_dist) def rating_dist(): conn sqlite3.connect(db.sqlite3) rows conn.execute( SELECT CASE WHEN rating 9 THEN 9分以上 WHEN rating 8 THEN 8到9分 WHEN rating 7 THEN 7到8分 ELSE 7分以下 END AS level, COUNT(*) AS count FROM movies GROUP BY level ).fetchall() conn.close() return jsonify([{level: r[0], count: r[1]} for r in rows])前端模板里这样接入fetch(/api/rating_dist) .then(res res.json()) .then(data { const chart echarts.init(document.getElementById(ratingChart)); chart.setOption({ title: { text: 豆瓣Top250评分分布 }, tooltip: {}, xAxis: { data: data.map(d d.level) }, yAxis: { type: value }, series: [{ type: bar, data: data.map(d d.count) }] }); });关键点在于data.map(d d.level)和data.map(d d.count)这一步把接口返回的对象数组拆成了两个纯数组正好对齐ECharts的xAxis.data和series.data结构。如果接口字段名和前端取的对不上图表会没有任何报错地显示空白这是最常见的排错点。5. 排错顺序与答辩准备这个系统最容易翻车的几个位置5.1 爬虫返回登录页或验证码时的排查顺序采集阶段最容易遇到的现象是页面能打开但解析不到电影条目。先打印resp.status_code和len(resp.content)对比正常值然后看返回内容里有没有“登录”或“验证”关键词。常规处理顺序是先换更完整的UA和Referer再补Cookie最后把time.sleep(2)的间隔拉到5秒。整套系统里爬虫只需要跑一次跑慢一点完全不影响使用。注意不要用代理池之类的重型方案毕业设计用不上也涉及合规风险保持低频率采集就够。5.2 接口有数据但图表空白三个必查位置排查位置检查方法常见原因接口返回浏览器直接访问/api/rating_dist数据格式不对字段名拼写错误DOM容器检查div是否有高度ECharts容器默认高度为0需要显式styleheight:400pxJS引入顺序开发者工具Console看报错echarts.min.js没有加载成功容器高度为0是高频错误。ECharts初始化时如果容器不可见或高度为0图表渲染出来是一张空白图且控制台不报错。给容器一个明确的高度是成本最低的解决方案。5.3 答辩时怎么讲这个系统的亮点评阅老师最关注的不是爬虫部分而是“分析”和“可视化”这两个高阶词。你可以把第4章的聚合SQL作为讲解重点说清楚为什么要分段统计评分、为什么类型要提前拆列。准备一张运行截图展示接口返回的JSON和前端图表同时出现在一个页面上这比讲十页PPT都有说服力。系统设计时留一个自定义筛选条件的扩展点——按评分区间过滤这就是你工作量的一部分也是答辩时最能聊的地方。本文还有配套的精品资源点击获取

相关新闻

okbiye外文翻译板块全解析:专业学术翻译攻略

okbiye外文翻译板块全解析:专业学术翻译攻略

外文文献是毕设的重要参考资料,很多高质量研究成果都是英文发表的,不读外文文献写不出高质量论文。但很多同学英文不好,看外文文献像看天书,一篇十几页英文论文啃一周都啃不完,用普通翻译软件机翻质量又差,…

2026/9/23 2:15:52 阅读更多 →
九号M95C大灯升级选型:四档透镜参数、DC配套与施工验收

九号M95C大灯升级选型:四档透镜参数、DC配套与施工验收

本文从光学结构和电气配套角度,梳理九号 M95C 升级透镜大灯总成的选型与施工要点,覆盖 KUS 135W、KUS 紫色妖狐 185W、恒威雾道 P9 200W、杜玛珂传承 M8 200W 四档方案(均为碧烽九号 M 系三透镜总成,M95C 全适配)&…

2026/9/23 2:14:51 阅读更多 →
VR虚拟现实设计培训机构推荐:从报名学习到考试拿证,报考全攻略

VR虚拟现实设计培训机构推荐:从报名学习到考试拿证,报考全攻略

虚拟现实(VR)正在改变游戏、教育、医疗、工业等行业的内容形态,VR虚拟现实设计师作为新兴内容人才,需求持续增长。本文给你一份完整的VR虚拟现实设计报考全攻略。 一、VR虚拟现实设计是做什么的? VR虚拟现实设计是围绕…

2026/9/23 2:14:51 阅读更多 →

最新新闻

药品板蓝根颗粒检测:110张VOC+YOLO数据集训练与避坑指南

药品板蓝根颗粒检测:110张VOC+YOLO数据集训练与避坑指南

简介:这份数据集面向计算机视觉开发者与药品检测场景,旨在解决板蓝根颗粒袋装产品的自动识别与定位问题。资源采用Pascal VOC与YOLO双格式标注,并保留原始JPG图片,能够直接用于YOLO系列、SSD、Faster R-CNN等主流目标检测模型的训…

2026/9/23 22:08:59 阅读更多 →
多 Loop 协调实战:在 loop-engineering 中用状态文件、优先级与 advisory lock 防止 Agent 循环互相打架

多 Loop 协调实战:在 loop-engineering 中用状态文件、优先级与 advisory lock 防止 Agent 循环互相打架

人工智能AI AgentAgent 工作流CLI研发协作AI 技能MCP 服务 【免费下载链接】loop-engineering Practical patterns, starters & CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and …

2026/9/23 22:08:59 阅读更多 →
YOLOv5遥感目标识别实战:从切图训练到部署的完整指南

YOLOv5遥感目标识别实战:从切图训练到部署的完整指南

简介:基于YOLOv5的遥感图像目标识别项目资源包,面向计算机视觉初学者、毕业设计学生和相关研究人员,聚焦卫星图像中目标检测的工程落地与代码复现,涵盖影像预处理、模型训练与识别评估等完整流程。压缩包共156个文件,体…

2026/9/23 22:08:59 阅读更多 →
CrossFormer图像分类实战:跨尺度注意力机制与训练避坑指南

CrossFormer图像分类实战:跨尺度注意力机制与训练避坑指南

简介:CrossFormer实战资源包面向图像分类方向的开发者与研究人群,聚焦跨尺度注意力机制对多尺度特征交互的改进,可用于复现分类实验、替换骨干网络,或在此基础上改造模型以适应自定义任务。压缩包共2000个文件,大小约8…

2026/9/23 22:08:59 阅读更多 →
模式识别实验Python代码全攻略:贝叶斯、KNN、聚类与PCA可运行实现

模式识别实验Python代码全攻略:贝叶斯、KNN、聚类与PCA可运行实现

简介:面向《模式识别》课程学习者,这份基于Python的实验代码包提供了贝叶斯分类器(性别分类)、Fisher线性判别、KNN近邻分类和PCA人脸识别等经典实验的完整可运行代码。每个实验均配有对应Python脚本和实验报告文档,便…

2026/9/23 22:08:59 阅读更多 →
Relay Client-Only Data 完全指南:用 Client Schema Extensions 在浏览器端扩展 GraphQL 数据模型

Relay Client-Only Data 完全指南:用 Client Schema Extensions 在浏览器端扩展 GraphQL 数据模型

前端开发工具 【免费下载链接】relay Relay is a JavaScript framework for building data-driven React applications. 项目地址: https://gitcode.com/gh_mirrors/relay29/relay 点击查看 免费下载 Relay 允许开发者通过 Client Schema Extensions(客…

2026/9/23 22:07:58 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/23 4:55:02 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/23 4:49:06 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/23 9:53:41 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/23 9:53:40 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/23 9:53:40 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/23 9:53:40 阅读更多 →