跳转至

2022-回放-06:Web 开发导论(HTTP 与 Web 技术演变)· Flask 实战 · FastAPI 初识

内容梗概

本次直播回放是课程三大实战模块(Web 开发 → Web 爬虫 → 数据可视化)的开端。老师先阐述了三次实战课层层递进的设计逻辑(Web 开发是互联网基石;爬虫方案恰好对应 Web 技术架构的演变;爬取的数据再拿去做可视化),随后用画图的方式从零推演 Web 的基本概念:HTTP 协议、web 服务器、静态网页、后端动态生成、AJAX、前后端分离四个发展阶段,并用 HFS 软件、百度首页、B 站弹幕做了现场演示。后半场进入 Flask 实战:用 pipenv 建虚拟环境、写第一个 Flask 应用、路由与装饰器、templates 模板与 Jinja 语法、static 静态文件、debug 模式。最后对照演示了 FastAPI 的最小示例(uvicorn 运行、自动返回 JSON、路径参数、typing 类型标注),并布置了"用 Flask 做一个博客性质网站"的作业。

知识点详解

一、课程结构说明(约 00:00 - 07:20)

  • 后三次实战是阶梯关系:Web 开发 → Web 爬虫 → 数据可视化。
  • Web 开发是互联网的基石:绝大多数 App 本质是"混合应用"(Web 技术套壳),小程序的 WXML 是 HTML 的变种。
  • 爬虫方案与 Web 技术架构演变一一对应:静态站直接爬、动态站要处理 JS 渲染甚至用无头浏览器;从开发者视角思考目标站的数据组织与前后端对接方式,是爬虫的关键思路,也体现安全专业"对抗"的内核。
  • 数据可视化:爬来的几千几万条数据靠工具处理,如统计词频(TF-IDF)、画词云。
  • 授课思路说明:以 Python 为线索串起计算机领域的知识体系;实战部分每个单点不求讲透,而是提供"索引",供学生按脉络自行展开。

二、Web 基本概念与技术演变(约 07:20 - 01:08:30)

  • 最原始形态(约 07:50):Web 本质 = 通过 HTTP 协议(超文本传输协议)传输一串文本并在浏览器显示。对面电脑有个文件夹 A,浏览器想看里面的 1.txt——需要双方先约定"暗号",这就是协议。
  • HTTP 方法(约 10:55):约定若干动作——GET(从对方获取)、POST(往对方发送)、PUT/UPDATE(更新已传内容)、DELETE(删除)。请求行如 GET /1.txt,路径本质是相对 web 目录的相对路径。
  • web 服务器(约 13:50):右边电脑也需要软件解析 HTTP 请求并操作文件夹,即 web server(WS):收到 GET / 就列出目录内容,收到 GET /1.txt 就返回文件内容。常见 web 服务器:Apache、Nginx、Tomcat(Java 系)。
  • 端口与多站点(约 15:50 - 17:30):web server 通过配置文件把端口映射到目录(80 端口 ↔ A 文件夹);http 默认 80 端口、https 默认 443,访问 :8080 说明开了第二个站点对应 B 文件夹——一台机器可同时跑 N 个网站。
  • HFS 演示(约 17:50 - 21:50):用 Http File Server(约 2.5MB 小软件)现场演示:add folder from disk 把桌面 demo 文件夹映射为 /demo,浏览器访问即可看到 1.txt、2.txt 的内容——浏览器与 web server 甚至可以在同一台机器上。
  • 阶段一:静态网页(约 22:00 - 26:50):需求升级(富文本:加粗、标题、图片)催生了 HTML。所有 web server 默认会在路径下寻找 index.html 并自动打开(约定俗成,index = 索引),这就是为什么网页课第一个文件总叫 index.html。静态网页一保存内容就固定,连"您是第 N 位访客"都做不到。
  • 阶段二:后端动态生成(约 26:50 - 33:00):web server 后面不再直接对文件夹,而是转发给一个**程序**(Python / PHP / Java / C 都行):根据 URL 路径找到对应脚本和函数,把 GET 参数(?id=256 问号后面是参数、前面是路径)传进去,函数生成一个符合 HTML 格式的字符串返回——页面"动"起来了。PHP 在安全领域常见(老站多、题多)。局限:拿到 HTML 后不再发请求,不按 F5 页面不会变——做不了弹幕。
  • 阶段三:AJAX(约 33:00 - 41:20):返回的不只 HTML,还有 CSS(管样式)和 JavaScript(管交互、在浏览器里运行)。JS 可以不刷新页面偷偷再发 GET 请求(如每秒取一次弹幕),拿到数据后修改页面局部元素。AJAX = Asynchronous JavaScript And XML:异步(不等上一个请求返回就能发下一个)、早期数据格式是 XML。
  • 阶段四:前后端分离(约 41:20 - 57:45):阶段三下后端生成 HTML、前端 JS 也改 HTML,两者"抢活"产生分歧;于是分家——前端(Node.js 生态的 Vue / React / Angular 框架)全权负责 HTML 呈现,后端(Python/PHP 等)只提供 URL 接口、返回数据。数据格式从 XML 演变为 JSON(JavaScript Object Notation):XML 复杂且像 HTML,JSON 长得像 Python 字典、能被 JS 原生解析,现在互联网上 99% 用 JSON(机制仍叫 AJAX)。前后端可跑在不同服务器上,后端可做负载均衡;多终端共用同一后台(浏览器/App/小程序/平板访问 B 站,数据一样只是呈现不同)——这是前后端分离成为大趋势的根本原因。
  • 实例观察(约 57:50 - 01:08:30):
  • 百度首页:直接爬到的 HTML 是空架子(logo、搜索框、热搜都不在里面),里面一堆 <script>;浏览器运行 JS 后用 AJAX 取数据再修改 HTML 渲染出页面。爬虫不是浏览器、没有 JS 运行环境,所以爬到的页面和看到的不一致——这是爬虫失败的常见原因。
  • B 站直播弹幕:F12 开发者工具 → 网络 → 过滤 Fetch/XHR,双手离开键盘也能看到请求数不断增长——JS 在后台持续取弹幕。百度首页则加载后不再发新请求,只用 JS 修改自身元素。

三、Flask 实战(约 01:08:30 - 01:58:50)

  • 框架对比:Python 常见 web 框架三个——Flask(轻量级、小而精、功能靠插件,适合教学)、Django(大而全、开箱即用,讲起来太庞大)、FastAPI(新生框架,天生为前后端分离的纯后端 API 设计)。Flask 设计之初是阶段三方案(含前端模板),装插件后也能做阶段四。
  • 作业要求(约 01:11:40 与结尾 02:25:30):用 Flask 做一个网站(博客、新闻站、班级网站均可);老师会建空仓库,不提供任何结构化文件;录播的 Flask 实例视频有 40 多分钟从零做博客的全流程,跟着做一定能做出来。
  • 项目初始化(约 01:14:25):新建文件夹 → VS Code 打开 → 终端 pipenv install 建虚拟环境 → 改 Pipfile 里的源为国内镜像 → pipenv shell 进入环境 → pipenv install flask。VS Code 右下角要选择刚创建的虚拟环境,否则 import 处有波浪线。
  • 最小应用(约 01:16:35):新建 app.py(web 应用也叫 app):
    from flask import Flask          # 导入 Flask 类
    app = Flask(__name__)             # 实例化应用
    @app.route('/')                   # 装饰器:定义路由,把路径绑定到函数
    def index():
        return 'hello world'
    
    @app.route('/') 写在函数前是**装饰器**(原理见"函数与类"章节视频),含义:用户访问该路径时自动运行对应函数——一种路径与函数的绑定关系。
  • web server 在哪里(约 1:22:50 - 1:28:00):Flask 内置了开发用 web 服务器(Werkzeug,德语"工具"),它承担两个角色:① 接收浏览器的 HTTP 请求;② 自动找到并执行 app.py。开发学习阶段不需要单独装 Apache/Nginx。文件名默认必须是 app.py;若叫别的名字(如 hello.py),需设置环境变量 FLASK_APP=hello 再运行。
  • 两种运行方式(约 01:29:00):
  • 代码末尾加 app.run(),直接 python app.py(符合直觉);
  • 命令行 flask run(官方方式)。注意:flask run 本质上也是导入执行 app.py,若文件里裸写 app.run() 会重复运行,所以要用 if __name__ == '__main__': 包起来——正好用上模块与包章节的知识。
  • templates 模板(约 01:33:00 - 01:44:00):动态页面的 HTML 大部分内容人人相同,只有局部要改——把整体 HTML 叫**模板**(类比群发邀请函只改姓名/称谓)。Flask 内置规则:默认去 app.py 同级目录下找 templates 文件夹;视图函数改为 return render_template('index.html')(需 from flask import render_template)。路径是相对 templates 的相对路径(如子目录就写 'pub/index.html');强迫症想改文件夹名,可在 Flask(__name__, template_folder='abc') 里指定。
  • Jinja 模板语言(约 01:45:00 - 01:53:30):所有现代 web 框架都有自己的模板语言(Java 的 JSP 同理);Flask 用 Jinja。HTML 里写 {{ name }}(双大括号)表示此处显示 Python 传来的变量;后端 render_template('index.html', name=username) 传参(前一个 name 是模板里的变量名,后一个是函数内变量)。还可用 {% %} 做分支/循环(语法见录播视频,含模板继承)。演示:首页显示"欢迎{username}来到我的首页"+ 用 datetime.now().strftime('%Y-%m-%d %H:%M:%S') 显示当前时间(%Y 四位年份、%m 月、%d 日、%H 时、%M 分、%S 秒,老师也是现场查的)。
  • static 静态文件(约 01:54:00 - 01:58:00):CSS、JS、图片等不需要后端计算的文件叫静态文件,默认放 static 文件夹(可再分 css/js/image 子目录),HTML 里用 link 等标签引用。可用 Flask(__name__, static_folder='...') 改名;甚至 static_host 参数可把静态文件放到另一台服务器——浏览器拿到 HTML 后自己去那台服务器下载静态资源,实现**数据/计算与静态资源分离**,减轻 app 服务器压力(进阶内容,不懂不影响)。
  • debug 模式(约 01:39:50、01:41:30):app.run(debug=True) 开启后,改代码 Ctrl+S 保存即自动 reload(终端显示 detected change... reloading),不用反复 Ctrl+C 重启。上线必须关掉:否则报错会把路径、代码细节直接打在网页上造成信息泄露(网安人的职业素养)。

四、FastAPI 初识(约 01:59:40 - 02:25:30)

  • 目的:通过对比理解阶段四(前后端分离)的框架长什么样。
  • 安装与示例(约 02:00:40):新建目录 → pipenv 老套路(改源)→ pipenv install fastapi;uvicorn 需单独装:pipenv install "uvicorn[standard]"(方括号语法表示安装其基于 C 扩展的一系列额外依赖)。官方示例文件名是 main.py。
  • 最小示例:
    from fastapi import FastAPI
    app = FastAPI()
    @app.get('/')          # 直接把 HTTP 方法写进装饰器
    def read_root():
        return {'Hello': 'World'}
    
    运行用 uvicorn main:app(main:app = 文件名:应用对象名,uvicorn 相当于 Flask 的内置服务器 + 调度器双重角色,默认端口 8000)。
  • 自动返回 JSON(约 02:09:50):FastAPI 的示例根本不出现 HTML——视图函数返回 Python 字典,框架自动转成符合 JSON 格式的字符串发给前端。Flask 也能返回 JSON 但要手工转换,FastAPI 是全自动——它天生只为"返回数据"设计。
  • 路径参数(约 02:18:00):/items/{item_id} 把参数写进路径(区别于 ?id=233 的 GET 参数),如 /users/233 访问 ID 为 233 的用户;函数 def read_item(item_id: int, q: str = None) 自动从路径取参。Flask 也支持这种写法。
  • typing 类型标注(约 2:06:00):示例里 q: Union[str, None] = None、def f(name: str) -> str 是 Python 3.5+ 的类型提示语法——弥补 Python 变量无类型导致的"调用者乱传参"问题;-> 标注返回值类型。
  • flask.py / abc.py 翻车(约 02:00:00、02:14:00):项目文件夹不能叫 flask(import flask 会找到自己、循环依赖);把 main.py 改名 abc.py 后 uvicorn 报错——因为 Python 标准库真有一个叫 abc 的模块(abstract base classes),被优先搜到;改成"anjing.py"立刻成功。生动复习了模块搜索路径知识。
  • 框架选择建议:做大创等项目时,前后端分离模式下后端用 FastAPI 只管数据,前端交给会 Vue/React 的同学;Flask 也在向这个方向发展。

示例与演示

  1. HFS 静态文件服务器:把桌面 demo 文件夹映射为 /demo,浏览器访问列出并打开 1.txt/2.txt,演示"HTTP 取文件"的最原始形态。
  2. 百度首页源代码:右键查看源代码几乎找不到实质内容(空 HTML + 一堆 script),说明页面靠 JS 渲染;对比 B 站直播页 F12 的 Fetch/XHR 请求持续增长(弹幕 AJAX 轮询)。
  3. Flask 从零建站:pipenv 初始化 → 写 app.py(路由 / 返回 hello world、/about 返回"我")→ 两种运行方式 → 加 templates/index.html 用 render_template 渲染 → Jinja {{ name }} 传用户名和当前时间 → 建 static 文件夹 → 开 debug 热重载。
  4. FastAPI 最小示例:官方 example 复制为 main.py → uvicorn main:app → 浏览器访问 / 得到 {"Hello":"World"},访问 /items/1?q=xxx 演示路径参数与查询参数。
  5. 作业:用 Flask 做一个博客性质的网站(想挑战可用 Vue + FastAPI,但基准要求是 Flask);老师建空仓库,跟着 40 分钟的 Flask 实例录播视频可完成。

重点与难点

  • Web 四阶段演变(静态 → 后端动态生成 → AJAX 局部刷新 → 前后端分离)是整节课的主线,也是理解爬虫策略的钥匙:爬动态渲染页面时,直接拿到的 HTML 是空壳。
  • AJAX 的名字来源(异步 JavaScript and XML)与"JSON 取代 XML 但名字没改"的历史;JSON 与 Python 字典形态一致。
  • HTTP 请求结构:路径 vs ? 后的 GET 参数 vs 路径内嵌参数(/items/{id})三种传参位置。
  • Flask 的"内置规则":app.py 文件名、templates 文件夹、static 文件夹都是默认约定,可通过 Flask() 参数(template_folder、static_folder、static_host)覆盖。
  • @app.route 装饰器 = 路径与函数的绑定;flask run 时务必用 if __name__ == '__main__': 包住 app.run(),否则重复运行。
  • debug 模式仅用于开发,上线必须关闭(信息泄露风险)。
  • 文件/目录命名不要与标准库、第三方库重名(flask 目录、abc.py 两次现场翻车);标准库里有 abc(abstract base classes)模块。
  • uvicorn 的启动参数 main:app 是"模块:应用对象",改名要两处一起改。

关联内容

  • 直接承接上一讲(回放-05)的"模块与包、第三方库与虚拟环境":pipenv/Pipfile 工作流、if __name__ == '__main__'、模块搜索路径在本课全部复用并翻车验证。
  • 装饰器原理见录播章节"函数进阶与类";Flask 完整实例(模板继承、Jinja 语法、40 分钟博客实战)在对应录播视频中。
  • 本课是后续"Web 爬虫"的直接前置:爬虫各方案对应本课的 Web 架构演变(静态页直接爬 → AJAX 站需分析接口或用无头浏览器);再往后接"数据可视化"(词频统计、词云)。
  • 前后端分离部分提及的 Vue/React/Angular、Node.js 不属于本课程内容,仅作方向指引;相对路径/绝对路径、环境变量等前置知识来自早期章节与《计算机安全与维护》。