🚀

用 AI 批量生成博客文章:选题→大纲→撰写→发布,全程自动化

用 Python + Ollama 搭建博客文章自动生成器,从选题到成稿一键完成,支持多风格和排版输出。

👁️ - 次阅读

你有没有这种痛苦:想写博客,但选题选半天,大纲理不清,动笔写又卡壳,最后文章拖了两周还没发出去。

手动写太慢,AI 代写又怕查重。今天做一个批量博客文章生成器。选题→大纲→撰写→排版,全程自动化,本地跑,不花一分钱。

项目背景

个人博客需要持续更新,但写作是最耗时的环节。用 AI 辅助写作已经很常见,但大多数人只用 ChatGPT 问一个问题,生成一篇就停了。

真正的痛点是:批量生成、风格统一、自动排版、多渠道发布。

这个项目要解决的就是这些问题。用 Python 脚本 + 本地 LLM,实现从选题到发布的完整工作流。

技术选型

组件选择理由
写作引擎Ollama + LLaMA 3本地运行,无网络依赖
选题库手动维护 + 随机抽样控制内容质量
大纲生成结构化 prompt保证文章结构
撰写模块分步生成控制质量和长度
输出格式Markdown + Hugo 页面直接发布
风格控制模板 + 参数统一博客调性

Ollama 安装:

curl -fsSL https://ollama.com/install.sh | sh
ollama pull llama3:8b

实现步骤

第一步:项目结构

mkdir -p blog_generator/{topics,outline,drafts,final}
cd blog_generator
touch generator.py config.yaml topics.txt

目录说明:

  • topics/ — 选题库,每个文件一个主题
  • outline/ — 生成的文章大纲
  • drafts/ — 撰写草稿
  • final/ — 最终发布稿

第二步:配置文件 config.yaml

model: llama3:8b
temperature: 0.7
max_tokens: 2000

blog_style:
  tone: 技术教程
  audience: 开发者
  language: zh
  length: 中等

output:
  format: markdown
  include_toc: true
  tag_style: comma

prompt_templates:
  topic_selection: |
    你是一个博客内容策划。根据以下主题方向,生成5个具体的文章选题。
    要求:适合技术博客,有实际价值,标题吸引人。
    主题方向:{topic_direction}
  
  outline_generation: |
    为以下标题生成博客文章大纲。
    要求:包含引言、3-5个主要章节、总结。
    标题:{title}
  
  article_draft: |
    根据以下大纲撰写完整博客文章。
    风格:{tone}
    目标读者:{audience}
    要求:实用性强,代码示例丰富,字数800-1500。
    
    大纲:
    {outline}

第三步:选题库 topics.txt

# 格式:标题 | 方向标签 | 关键词
AI模型本地部署 | 技术教程 | ollama,本地LLM
Python自动化脚本 | 效率工具 | python,自动化,crontab
博客内容运营 | 运营技巧 | 博客,SEO,写作
Web开发实战 | 技术教程 | flask,fastapi,前端
数据可视化 | 数据分析 | matplotlib,可视化

第四步:核心生成器 generator.py

#!/usr/bin/env python3
"""AI 博客文章批量生成器"""

import os
import yaml
import random
import subprocess
from pathlib import Path
from datetime import datetime
import json

# ============ 配置加载 ============

def load_config():
    with open("config.yaml", encoding="utf-8") as f:
        return yaml.safe_load(f)

CFG = load_config()
MODEL = CFG["model"]

# ============ 工具函数 ============

def ollama_generate(prompt, max_tokens=2000):
    """调用 Ollama 生成内容"""
    result = subprocess.run(
        ["ollama", "run", MODEL, prompt],
        capture_output=True,
        text=True,
        timeout=120
    )
    return result.stdout.strip()

def read_topics():
    """读取选题库"""
    topics = []
    if Path("topics.txt").exists():
        with open("topics.txt", encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith("#"):
                    parts = line.split("|")
                    if len(parts) >= 3:
                        topics.append({
                            "title": parts[0].strip(),
                            "tag": parts[1].strip(),
                            "keywords": parts[2].strip()
                        })
    return topics

def save_file(content, filepath):
    """保存文件"""
    Path(filepath).parent.mkdir(parents=True, exist_ok=True)
    with open(filepath, "w", encoding="utf-8") as f:
        f.write(content)
    print(f"  ✅ 已保存: {filepath}")

# ============ 生成步骤 ============

def generate_topic_selection(topic_direction):
    """生成选题建议"""
    prompt = CFG["prompt_templates"]["topic_selection"].format(
        topic_direction=topic_direction
    )
    return ollama_generate(prompt)

def generate_outline(title, style_cfg):
    """生成文章大纲"""
    prompt = CFG["prompt_templates"]["outline_generation"].format(title=title)
    return ollama_generate(prompt)

def generate_article(outline, style_cfg):
    """撰写完整文章"""
    prompt = CFG["prompt_templates"]["article_draft"].format(
        tone=style_cfg["tone"],
        audience=style_cfg["audience"],
        outline=outline
    )
    return ollama_generate(prompt, max_tokens=CFG["max_tokens"])

def add_frontmatter(title, tags, date=None):
    """添加 Hugo frontmatter"""
    if date is None:
        date = datetime.now().strftime("%Y-%m-%d")
    
    tags_str = ", ".join(tags) if isinstance(tags, list) else tags
    
    frontmatter = f"""---
title: "{title}"
date: {date}
description: ""
tags: [{tags_str}]
draft: false
---
"""
    return frontmatter

def generate_slug(title):
    """生成 URL slug"""
    import re
    title = title.lower()
    title = re.sub(r'[^\w\s-]', '', title)
    title = re.sub(r'[\s]+', '-', title)
    return title.strip('-')

# ============ 主流程 ============

def generate_one_article(topic):
    """生成单篇文章"""
    title = topic["title"]
    print(f"\n📝 生成文章: {title}")
    
    # 步骤1: 生成大纲
    print("  📋 生成大纲...")
    outline = generate_outline(title, CFG["blog_style"])
    outline_path = f"outline/{generate_slug(title)}.txt"
    save_file(outline, outline_path)
    
    # 步骤2: 撰写文章
    print("  ✍️ 撰写文章...")
    article = generate_article(outline, CFG["blog_style"])
    draft_path = f"drafts/{generate_slug(title)}.md"
    save_file(article, draft_path)
    
    # 步骤3: 添加 frontmatter 和排版
    print("  📄 生成最终版本...")
    tags = [topic["tag"]] + topic["keywords"].split(",")
    frontmatter = add_frontmatter(title, tags)
    
    final_content = frontmatter + "\n" + article
    final_path = f"final/{generate_slug(title)}.md"
    save_file(final_content, final_path)
    
    return {
        "title": title,
        "slug": generate_slug(title),
        "outline": outline_path,
        "draft": draft_path,
        "final": final_path
    }

def generate_batch(count=3, random_topic=None):
    """批量生成文章"""
    topics = read_topics()
    
    if not topics:
        print("⚠️  选题库为空,请先编辑 topics.txt")
        return
    
    print(f"📚 共 {len(topics)} 个选题")
    print(f"🎯 本次生成 {count} 篇文章")
    
    if random_topic:
        selected = [random.choice(topics)]
    else:
        selected = random.sample(topics, min(count, len(topics)))
    
    results = []
    for topic in selected:
        try:
            result = generate_one_article(topic)
            results.append(result)
        except Exception as e:
            print(f"  ❌ {topic['title']}: {e}")
    
    print(f"\n🎉 完成!成功生成 {len(results)} 篇文章")
    return results

def add_new_topic(title, tag, keywords):
    """手动添加选题"""
    line = f"{title} | {tag} | {keywords}\n"
    with open("topics.txt", "a", encoding="utf-8") as f:
        f.write(line)
    print(f"✅ 已添加选题: {title}")

# ============ CLI 入口 ============

if __name__ == "__main__":
    import sys
    
    if len(sys.argv) < 2:
        print("用法:")
        print("  python generator.py batch [数量]      # 批量生成")
        print("  python generator.py single            # 随机生成一篇")
        print("  python generator.py add <标题> <标签> <关键词>")
        print("  python generator.py list              # 查看选题库")
        sys.exit(1)
    
    cmd = sys.argv[1]
    
    if cmd == "batch":
        count = int(sys.argv[2]) if len(sys.argv) > 2 else 3
        generate_batch(count)
    elif cmd == "single":
        generate_batch(1)
    elif cmd == "add":
        if len(sys.argv) < 5:
            print("用法: python generator.py add <标题> <标签> <关键词>")
            sys.exit(1)
        add_new_topic(sys.argv[2], sys.argv[3], sys.argv[4])
    elif cmd == "list":
        topics = read_topics()
        print(f"选题库(共 {len(topics)} 个):")
        for i, t in enumerate(topics, 1):
            print(f"  {i}. {t['title']} [{t['tag']}]")
    else:
        print(f"未知命令: {cmd}")

第五步:运行测试

# 查看选题库
python generator.py list

# 批量生成3篇文章
python generator.py batch 3

# 添加新选题
python generator.py add "AI编程助手对比" "技术评测" "cursor,claude,chatgpt"

# 随机生成一篇
python generator.py single

生成的文章直接放到 Hugo 的 content/blog/ 目录就能发布。

运行效果

生成完成后目录结构:

blog_generator/
├── topics.txt           # 选题库
├── config.yaml          # 配置文件
├── generator.py         # 生成器
├── outline/             # 大纲文件
│   └── ai-model-local-deployment.txt
├── drafts/              # 草稿
│   └── ai-model-local-deployment.md
└── final/               # 最终发布稿
    └── ai-model-local-deployment.md

最终文件内容示例:

---
title: "AI模型本地部署完全指南"
date: 2026-08-09
description: ""
tags: [技术教程, ollama, 本地LLM]
draft: false
---

# AI模型本地部署完全指南

...(文章内容)...

优化方向

  1. 自动发布:生成后自动 commit 到 Git,触发 CI/CD
  2. 配图生成:用 Stable Diffusion 自动生成文章配图
  3. SEO 优化:自动分析关键词密度,给出优化建议
  4. 多语言支持:配置 LANGUAGE 参数,一键生成英文版本
  5. 风格学习:读取历史文章,模仿已有风格
  6. 定时发布:配合 crontab,每天自动生成并发布

批量生成只是第一步,真正有价值的是持续产出。你的博客现在多久更新一次?


下一步:把生成的文章复制到 content/blog/,运行 hugo 构建,就能看到效果了。

这篇文章对你有帮助吗?