抓取的原始HTML不能直接当模板用,必须经结构标准化、模块拆分和占位符替换;因其含内联样式、硬编码路径、动态class等,缺乏可复用性与变量注入能力。

直接说结论:抓取到的原始HTML源码不能直接当模板用,必须先做结构标准化、模块拆分和占位符替换,否则后续填充数据时会出错或难以维护。
为什么不能把 raw HTML 当作模板直接保存
浏览器抓取的 curl 或 requests.get().text 返回的是「快照式」HTML:含内联样式、硬编码路径、动态生成的 class 名、甚至带时间戳的 script 标签。这类代码缺乏可复用性,也不支持变量注入。
- 比如图片路径是
<img src="/uploads/2026/08/report_v2.jpg">,下次填充新图就得手动改路径 - 标题写死为
<h1>Q2销售报告</h1>,无法通过参数切换成“Q3”或“用户反馈汇总” - 页脚可能混着 JS 初始化代码,一复制就破坏逻辑边界
如何把抓取内容转成真正可用的模板
核心动作是三步:清洗结构 → 拆出公共块 → 插入占位符。不是“另存为”,而是“重构为”。
- 用正则或 BeautifulSoup 清掉
<script>块(除非你明确要保留运行逻辑)和冗余注释 - 把
<header>、<footer>、<nav>等区块剪出来,分别存为header.tpl、footer.tpl - 在主模板里用注释标记插入点,例如
<!-- include:header -->,而不是直接粘贴代码 - 把所有动态内容替换成 Jinja2 风格占位符:
{{ title }}、{{ image_src }}、{{ content|safe }}(注意|safe防转义) - 保存时统一用
.html后缀,但文件名体现用途,如article_page.html,别叫backup_20260826.html
Python 里用 requests + jinja2 保存模板的最小可行示例
别用字符串拼接生成模板文件——它不处理转义、不校验嵌套、没法复用 block。直接上 jinja2.Template + FileSystemLoader 路径管理。
立即学习“前端免费学习笔记(深入)”;
from jinja2 import Environment, FileSystemLoader
<h1>假设你已用 requests 抓到原始 HTML 并清洗过</h1><p>raw_html = '''<!DOCTYPE html>
<html><head><title>{{ title }}</title></head>
<body><h1>{{ title }}</h1><p>{{ content }}</p></body></html>'''</p><h1>保存为模板文件(非渲染结果)</h1><p>with open('templates/base.html', 'w', encoding='utf-8') as f:
f.write(raw_html)</p><h1>后续渲染时才加载</h1><p>env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('base.html')
rendered = template.render(title="用户协议", content="本协议自2026年8月起生效...")注意:env.get_template() 读的是磁盘上的 .html 文件,不是内存里的字符串;render() 才真正执行变量替换。
容易被忽略的细节
很多人卡在「保存成功但渲染失败」,问题常出在三个地方:
- 文件编码没强制设
encoding='utf-8',中文占位符变成乱码,jinja2报UnicodeDecodeError - 把
{{ content }}直接塞进<script>或<style>里,没加|safe过滤,导致 HTML 被自动转义 - 模板路径写错,比如
Environment(loader=FileSystemLoader('./templates'))中的./是相对当前工作目录,不是脚本所在目录
真正难的不是保存动作本身,而是判断哪些内容该抽成变量、哪些该保留为静态结构——这得看业务场景,不是工具能自动决定的。



















