本文目录导读:

我来详细介绍几种用脚本批量生成静态网站的方法,从简单到复杂:
使用静态网站生成器(推荐)
Hugo (Go语言)
#!/bin/bash
# 批量生成Hugo网站
# 创建多个站点
for site_name in site1 site2 site3; do
hugo new site $site_name
cd $site_name
# 添加主题
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
echo 'theme = "ananke"' >> config.toml
# 生成内容
hugo new content posts/first-post.md
echo "---" > content/posts/first-post.md
echo "title: 'Welcome to $site_name'" >> content/posts/first-post.md
echo "date: $(date +'%Y-%m-%d')" >> content/posts/first-post.md
echo "---" >> content/posts/first-post.md
echo "This is $site_name." >> content/posts/first-post.md
# 构建
hugo
cd ..
done
Python + Pelican
#!/usr/bin/env python3
import os
import shutil
# Pelican生成脚本
sites = [
{"name": "blog1", "title": "Tech Blog"},
{"name": "blog2", "title": "Personal Site"},
{"name": "blog3", "title": "Project Docs"}
]
for site in sites:
os.makedirs(f"{site['name']}/content", exist_ok=True)
os.makedirs(f"{site['name']}/output", exist_ok=True)
# 创建配置文件
with open(f"{site['name']}/pelicanconf.py", "w") as f:
f.write(f"""
SITENAME = '{site['title']}'
SITEURL = 'https://example.com/{site['name']}'
PATH = 'content'
OUTPUT_PATH = 'output'
TIMEZONE = 'Asia/Shanghai'
DEFAULT_LANG = 'zh'
""")
# 创建文章
article = f"""Title: Welcome
Date: {os.popen('date +%Y-%m-%d').read().strip()}
Category: General
Welcome to {site['title']}!
"""
with open(f"{site['name']}/content/welcome.md", "w") as f:
f.write(article)
# 生成静态网站
os.system(f"cd {site['name']} && pelican content")
Node.js + Eleventy (11ty)
#!/usr/bin/env node
const fs = require('fs');
const { execSync } = require('child_process');
const sites = ['docs', 'blog', 'portfolio'];
sites.forEach(site => {
// 创建目录结构
fs.mkdirSync(`./${site}/src`, { recursive: true });
fs.mkdirSync(`./${site}/_site`, { recursive: true });
// 创建Eleventy配置
const config = `
module.exports = function(eleventyConfig) {
return {
dir: {
input: "src",
output: "_site"
}
};
};
`;
fs.writeFileSync(`./${site}/.eleventy.js`, config);
// 创建模板
fs.writeFileSync(`./${site}/src/index.njk`, `---
layout: base.njk ${site}
---
<h1>Welcome to ${site}</h1>
`);
// 创建布局
fs.mkdirSync(`./${site}/src/_includes`, { recursive: true });
fs.writeFileSync(`./${site}/src/_includes/base.njk`, `
<!DOCTYPE html>
<html>
<head><title>{{ title }}</title></head>
<body>
<main>{{ content | safe }}</main>
</body>
</html>
`);
// 构建
execSync(`cd ${site} && npx @11ty/eleventy`);
});
使用Python直接生成HTML
简单模板渲染
#!/usr/bin/env python3
import os
from string import Template
# HTML模板
HTML_TEMPLATE = Template("""
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">${title}</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>${title}</h1>
<nav>
<a href="/">首页</a>
<a href="/about.html">lt;/a>
<a href="/blog.html">博客</a>
</nav>
</header>
<main>
<h2>欢迎来到 ${title}</h2>
<p>${content}</p>
<p>更新时间: ${date}</p>
</main>
<footer>
<p>© ${year} ${title}</p>
</footer>
</body>
</html>
""")
# 站点数据
sites = [
{
"title": "技术博客",
"content": "分享编程知识和经验",
"pages": ["index", "about", "blog"]
},
{
"title": "个人网站",
"content": "展示个人作品和想法",
"pages": ["index", "about", "projects"]
}
]
for site in sites:
# 创建文件夹
dir_name = site["title"].replace(" ", "_")
os.makedirs(f"./output/{dir_name}", exist_ok=True)
# 生成页面
for page in site["pages"]:
html_content = HTML_TEMPLATE.safe_substitute(
title=f"{page.capitalize()} - {site['title']}",
content=f"{page.capitalize()} page content for {site['title']}",
date=os.popen('date +%Y-%m-%d').read().strip(),
year=os.popen('date +%Y').read().strip()
)
with open(f"./output/{dir_name}/{page}.html", "w", encoding="utf-8") as f:
f.write(html_content)
# 创建CSS
css_content = """
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
line-height: 1.6;
}
header { border-bottom: 2px solid #333; padding-bottom: 10px; }
nav a { margin-right: 15px; color: #0066cc; text-decoration: none; }
footer { border-top: 1px solid #ccc; padding-top: 10px; margin-top: 20px; }
"""
with open(f"./output/{dir_name}/style.css", "w") as f:
f.write(css_content)
print("网站批量生成完成!")
Shell脚本批量处理
基于已有模板
#!/bin/bash
# 批量生成类似结构的网站
TEMPLATE_DIR="./template"
SITES=("site-a" "site-b" "site-c")
for site in "${SITES[@]}"; do
# 复制模板
cp -r "$TEMPLATE_DIR" "./$site"
# 替换占位符
find "./${site}" -type f -exec sed -i "s/{{SITE_NAME}}/${site}/g" {} \;
# 自定义内容
echo "<p>Welcome to $site</p>" > "./$site/index.html"
# 生成sitemap
echo "https://example.com/$site" >> "./sitemap.txt"
echo "Generated: $site"
done
使用Makefile自动化
# Makefile for batch site generation
SITES = site1 site2 site3
HTML = index.html about.html contact.html
all: $(foreach site,$(SITES),gen-$(site))
gen-%:
@echo "Generating $*..."
@mkdir -p $*/public
@for page in $(HTML); do \
echo "<html><body><h1>Welcome to $*</h1><p>$$page</p></body></html>" > $*/public/$$page; \
done
@echo "✓ $* generated"
clean:
@rm -rf $(SITES)
.PHONY: all clean
推荐的工具和工作流程
完整示例:Python批量生成器
#!/usr/bin/env python3
"""
批量静态网站生成器
支持自定义模板、内容、配置
"""
import os
import json
import shutil
from datetime import datetime
from jinja2 import Environment, FileSystemLoader
class SiteGenerator:
def __init__(self, template_dir="templates"):
self.env = Environment(loader=FileSystemLoader(template_dir))
self.output_dir = "output"
def generate_site(self, site_config):
"""生成单个站点"""
site_name = site_config["name"]
site_dir = os.path.join(self.output_dir, site_name)
os.makedirs(site_dir, exist_ok=True)
# 生成页面
for page in site_config.get("pages", []):
template = self.env.get_template(f"{page['template']}.html")
html = template.render(
title=page.get("title", site_name),
content=page.get("content", ""),
date=datetime.now().strftime("%Y-%m-%d"),
site_name=site_name
)
with open(os.path.join(site_dir, f"{page['name']}.html"), "w") as f:
f.write(html)
# 复制静态资源
if os.path.exists("static"):
for item in os.listdir("static"):
src = os.path.join("static", item)
dst = os.path.join(site_dir, item)
if os.path.isfile(src):
shutil.copy2(src, dst)
else:
shutil.copytree(src, dst)
return site_dir
def batch_generate(self, config_file="sites.json"):
"""批量生成所有站点"""
with open(config_file, "r") as f:
sites_config = json.load(f)
for site in sites_config:
result = self.generate_site(site)
print(f"Generated: {result}")
# 使用示例
if __name__ == "__main__":
generator = SiteGenerator()
generator.batch_generate()
sites.json配置示例
[
{
"name": "tech-blog",
"pages": [
{
"name": "index",
"template": "default",
"title": "技术博客",
"content": "分享编程知识"
},
{
"name": "about",
"template": "default",
"title": "关于我",
"content": "全栈开发者"
}
]
},
{
"name": "photo-gallery",
"pages": [
{
"name": "index",
"template": "gallery",
"title": "摄影作品",
"content": "展示摄影作品"
}
]
}
]
推荐工具选择
| 工具 | 适合场景 | 学习曲线 | 性能 |
|---|---|---|---|
| Hugo | 大型文档站、博客 | 中等 | 极快 |
| Eleventy | 灵活的项目 | 中等 | 快 |
| Pelican | Python开发者 | 低 | 中等 |
| 手写Python | 完全自定义 | 中等 | 中等 |
最佳实践
- 使用模板引擎:Jinja2 (Python)、Nunjucks (Node.js)
- 分离配置和内容:使用JSON/YAML配置,Markdown内容
- 增量构建:只重新生成修改过的页面
- 缓存处理:对静态资源添加哈希
- 并行构建:使用多进程加速
选择哪种方法取决于你的具体需求、技术栈和网站规模,对于简单需求,直接使用SSG工具;对于复杂自定义场景,使用脚本生成更灵活。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播