本文目录导读:

- 文章标题:从零到一:手把手教你用Python脚本自动生成静态网站(无需框架)
- 目录导读
- 为什么用脚本生成网站?
- 前置准备
- 核心逻辑拆解(三步曲)
- 实战演练(核心代码片段)
- 自动化部署:让网站“活”起来
- 常见问题解答(FAQ)
从零到一:手把手教你用Python脚本自动生成静态网站(无需框架)
目录导读
- 为什么用脚本生成网站? —— 传统建站 vs 脚本化优势
- 前置准备 —— 环境搭建与核心工具(Python + Jinja2)
- 核心逻辑拆解 —— 模板、数据、渲染的三步曲
- 实战演练 —— 生成一个包含博客列表与详情页的完整网站
- 自动化部署 —— 将脚本接入GitHub Actions实现一键更新
- 常见问题解答(FAQ) —— 解决路径、编码、动态交互的痛点
为什么用脚本生成网站?
假设你维护着一个产品文档站,每月需要更新100个HTML页面,手工复制粘贴不仅耗时,还极易出错,而脚本生成(Static Site Generator) 的核心思想是:(Markdown/JSON)与表现(HTML模板)分离,通过一段脚本自动将两者合并输出为纯静态文件。
对比传统CMS(如WordPress):
- 速度:无数据库查询,页面加载毫秒级。
- 安全:无动态执行漏洞,可托管于任何CDN。
- 成本:可部署在免费托管(如GitHub Pages),近乎零成本。
关键数据:谷歌SEO研究表明,页面加载时间从1秒增至3秒,跳出率增加32%,静态网站正是性能优化的最优解。
前置准备
- Python 3.8+ (推荐使用虚拟环境
python -m venv venv) - Jinja2模板引擎(安装命令:
pip install jinja2) - Markdown解析库(可选,用于内容格式化:
pip install markdown)
目录结构规划:
project/
├── scripts/generate.py # 主脚本
├── templates/ # HTML模板
│ ├── base.html # 基础骨架
│ └── post.html # 博文详情模板
├── content/ # 内容源(Markdown或JSON)
│ └── posts/ # 每篇博文
└── output/ # 程序生成的站点
核心逻辑拆解(三步曲)
第一步:定义数据模型以结构化方式存放,每篇博客用Markdown文件,头部包含元数据:
--- "我的第一篇脚本生成文章" date: 2025-04-01 tags: [教程, Python] ---…
在脚本中,我们读取这些文件并用 frontmatter 库解析。
第二步:设计模板
base.html 定义全局布局(导航、页脚)。post.html 继承基础模板并插入内容变量:
{% extends "base.html" %}
{% block content %}
<article>
<h1>{{ post.title }}</h1>
<p>{{ post.date }}</p>
<div>{{ post.body_html | safe }}</div>
</article>
{% endblock %}
第三步:渲染并输出文件,将数据注入模板,写到 output/ 目录,同时生成首页列表页,循环展示所有文章标题与摘要。
实战演练(核心代码片段)
以下为 generate.py 的关键逻辑:
from jinja2 import Environment, FileSystemLoader
import markdown, frontmatter, os, glob
env = Environment(loader=FileSystemLoader('templates'))
def render_posts():
template = env.get_template('post.html')
posts_data = []
for md_file in glob.glob('content/posts/*.md'):
post = frontmatter.load(md_file)
html_body = markdown.markdown(post.content)
# 构建输出路径
slug = os.path.splitext(os.path.basename(md_file))[0]
output_path = f'output/posts/{slug}.html'
os.makedirs(os.path.dirname(output_path), exist_ok=True)
# 渲染并写入
html = template.render(post=post, body_html=html_body)
with open(output_path, 'w') as f:
f.write(html)
posts_data.append({'title': post['title'], 'url': output_path})
# 生成首页列表
index_template = env.get_template('index.html')
index_html = index_template.render(posts=posts_data)
with open('output/index.html', 'w') as f:
f.write(index_html)
if __name__ == '__main__':
render_posts()
执行结果:运行 python scripts/generate.py 后,output/ 下出现完整的 index.html 和若干文章页面,直接双击即可预览。
自动化部署:让网站“活”起来
手动跑脚本太Low?利用GitHub Actions,实现“推代码即更新”:
- 将项目推送到GitHub仓库。
- 在仓库中创建
.github/workflows/deploy.yml大致如下:
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- run: pip install -r requirements.txt
- run: python scripts/generate.py
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./output
这样,每次你更新 content/ 下的文章并推送后,网站自动重新生成并部署。
常见问题解答(FAQ)
Q1:输出的静态页面能否包含搜索功能?
可以,推荐用客户端的 lunr.js 或 Pagefind,在生成时同步构建索引JSON文件即可。
Q2:如何处理图片路径和相对链接?
在模板中使用 {{ url_for('static', path='') }} 或在前置元数据中定义 base_url,确保绝对路径。
Q3:本地预览时需要起服务器吗?
不需要,直接双击HTML即可,但为模拟真实环境(特别是相对路径),建议运行 python -m http.server 8000。
Q4:脚本能生成多语言网站吗?
能,将语言作为前置字段,用两个模板文件夹或根据语言后缀分别渲染,只需在循环中增加一步 if lang == 'zh' 的逻辑。
Q5:遇到中文字符乱码怎么办?
统一在Python文件头部写 # -*- coding: utf-8 -*-,且保存HTML时使用 encoding='utf-8',同时确保Jinja2模板声明 <meta charset="UTF-8">。
通过这几步,你已经掌握了一种高效、可控、且对SEO极其友好的建站方式,下次当网站内容爆发式增长时,你只需写一篇Markdown,剩下的,交给脚本,若想把网站部署到自己域名下,建议绑定 yourdomain.com 并配置HTTPS,但请注意,如果文中出现示例域名,请一律使用 example.com 以保证规范。